Commit b3033f79 by 邓敏

Merge branch 'websocker'

2 parents b8a6f5cc 2c64b3b6
Showing with 1158 additions and 155 deletions
......@@ -66,7 +66,7 @@
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.64</version>
<version>3.1.322</version>
</dependency>
<dependency>
......@@ -221,6 +221,22 @@
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.322</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-mongodb</artifactId>-->
......
......@@ -3,6 +3,7 @@ package com.subsidy;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.RestController;
......@@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@MapperScan(basePackages = {"com.subsidy.mapper"})
@EnableScheduling
@EnableCaching
@EnableAsync
public class MeishuApplication {
......
package com.subsidy.common.configure;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "activity")
public class ActivityDetectionConfig {
private Long captchaAppId;
private String appSecretKey;
private Long businessId;
}
package com.subsidy.common.constant;
import lombok.Getter;
@Getter
public class VodConstant {
/* 流量 */
public final static String FLUX = "Flux";
/* 带宽 */
public final static String BANDWIDTH = "Bandwidth";
/* 请求数 */
public final static String REQUESTS = "Requests";
/* 请求命中率 */
public final static String HITRATE = "Hitrate";
/* IP访问次数 */
public final static String IP_VISITS = "Ip_visits";
/* 带宽缓存key */
public final static String BANDWIDTH_CACHE_KEY = "CDNStatBandwidthCache";
/* 流量缓存key */
public final static String FLUX_CACHE_KEY = "CDNStatFluxCache";
/* 自定义缓存名称(ehcache.xml中的自定义规则名称) */
public final static String CDN_STAT_DETAILS_CACHE_NAME = "CDNStatDetails";
}
......@@ -103,4 +103,6 @@ public class AccessTokenController {
signVO.setSign(SecretUtils.getSHAString(signStr));
return ResponseData.generateCreatedResponse(0,signVO);
}
}
......@@ -4,8 +4,8 @@ package com.subsidy.controller;
import com.subsidy.common.ResponseData;
import com.subsidy.common.ResponseVO;
import com.subsidy.common.interceptor.TimeRequired;
import com.subsidy.dto.detection.GetCheckHistoryDTO;
import com.subsidy.dto.detection.VerifyDTO;
import com.subsidy.model.ActivityDetectionDO;
import com.subsidy.service.ActivityDetectionService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -43,11 +43,8 @@ public class ActivityDetectionController {
@PostMapping("getCheckHistory")
@ApiOperation("获取某个人某个课程的活跃度验证详情 memberId classId")
public ResponseVO getCheckHistory(@RequestBody ActivityDetectionDO activityDetectionDO){
return ResponseData.generateCreatedResponse(0,activityDetectionService.getCheckHistory(activityDetectionDO));
public ResponseVO getCheckHistory(@RequestBody GetCheckHistoryDTO getCheckHistoryDTO){
return ResponseData.generateCreatedResponse(0,activityDetectionService.getCheckHistory(getCheckHistoryDTO));
}
}
......@@ -77,4 +77,11 @@ public class CompanyDictController {
return ResponseData.generateCreatedResponse(0,companyDictService.getCompanyMembers(getCompanyMembersDTO));
}
@PostMapping("memberSummary")
@ApiOperation("学员认证详情 companyId")
@LoginRequired
public ResponseVO memberSummary(@RequestBody GetCompanyMembersDTO getCompanyMembersDTO){
return ResponseData.generateCreatedResponse(0,companyDictService.memberSummary(getCompanyMembersDTO));
}
}
......@@ -4,6 +4,7 @@ package com.subsidy.controller;
import com.subsidy.common.ResponseData;
import com.subsidy.common.ResponseVO;
import com.subsidy.common.interceptor.LoginRequired;
import com.subsidy.dto.image.ImageCheckDTO;
import com.subsidy.model.ImageCheckRecordDO;
import com.subsidy.service.ImageCheckRecordService;
import io.swagger.annotations.ApiOperation;
......@@ -32,12 +33,17 @@ public class ImageCheckRecordController {
@Autowired
private ImageCheckRecordService imageCheckRecordService;
@PostMapping("getImageCheckHistory")
@ApiOperation("获取某人某个班级的验证历史 memberId classId ")
@LoginRequired
public ResponseVO getImageCheckHistory(@RequestBody ImageCheckRecordDO imageCheckRecordDO){
return ResponseData.generateCreatedResponse(0,imageCheckRecordService.getImageCheckHistory(imageCheckRecordDO));
public ResponseVO getImageCheckHistory(@RequestBody ImageCheckRecordDO imageCheckRecordDO) {
return ResponseData.generateCreatedResponse(0, imageCheckRecordService.getImageCheckHistory(imageCheckRecordDO));
}
@PostMapping("imageCheck")
@ApiOperation("人身核验 id 用户id nonce ")
public ResponseVO imageCheck(@RequestBody ImageCheckDTO imageCheckDTO) throws Exception {
return ResponseData.generateCreatedResponse(0, imageCheckRecordService.imageCheck(imageCheckDTO));
}
......
......@@ -102,13 +102,6 @@ public class MemberController {
return ResponseData.generateCreatedResponse(0,memberService.updatePassword(memberDO));
}
@PostMapping("updateCheckImage")
@ApiOperation("上传采集照片 id checkImage")
@TimeRequired
public ResponseVO updateCheckImage(@RequestBody MemberDO memberDO){
return ResponseData.generateCreatedResponse(0,memberService.updateCheckImage(memberDO));
}
@PostMapping("removeCheckImage")
@ApiOperation("清除采集照片 id ")
public ResponseVO removeCheckImage(@RequestBody MemberDO memberDO){
......
......@@ -45,7 +45,7 @@ public class VodPlayHistoryController {
@RequestMapping("insertHistoryNew")
@ApiOperation("记录学生看视频位置 classId班级id vodId 视频id memberId 成员id playLength 播放时长 playRecord 位点")
// @LoginRequired
@LoginRequired
@TimeRequired
public ResponseVO insertHistoryNew(@RequestBody String param){
InsertHistoryNewDTO insertHistoryNewDTO = JSON.parseObject(param, InsertHistoryNewDTO.class);
......
package com.subsidy.dto.company;
import lombok.Data;
@Data
public class DataOverviewDTO {
private Long companyId;
}
package com.subsidy.dto.detection;
import lombok.Data;
@Data
public class GetCheckHistoryDTO {
private Integer pageSize;
private Integer pageNum;
private Long memberId;
private Long classId;
}
package com.subsidy.dto.image;
import lombok.Data;
@Data
public class ImageCheckDTO {
private Long id;
private String imageBase64;
private Long classId;
private Long paperId;
private String nonce ;
}
package com.subsidy.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.subsidy.model.ActivityDetectionDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.subsidy.vo.activity.GetCheckHistoryVO;
import org.springframework.stereotype.Repository;
/**
......@@ -15,4 +17,6 @@ import org.springframework.stereotype.Repository;
@Repository
public interface ActivityDetectionMapper extends BaseMapper<ActivityDetectionDO> {
IPage<GetCheckHistoryVO> getCheckHistory(IPage iPage,Long classId,Long memberId);
}
......@@ -53,4 +53,6 @@ public interface ClassDictMapper extends BaseMapper<ClassDictDO> {
* 班级信息 -- 获取课程信息 + 公司信息
* */
ClassAndCompanyInfoVO getClassAndCompanyInfoVO(Long classId);
Integer getClassCount();
}
......@@ -97,4 +97,9 @@ public interface VodPlayHistoryMapper extends BaseMapper<VodPlayHistoryDO> {
List<VodPlayHistoryDO> getVodPlayDay(Long classId, Long memberId, Date endDate);
double getStudyTotal();
double getSubsidyStudyTotal();
int getStudyHistoryNum();
}
......@@ -78,6 +78,45 @@ public class ClassDictDO extends BaseModel {
*/
private Integer testRule;
/**
* 学习上限时长
*/
private Integer limitHour;
/**
* 首次进入班级时人脸验证
*/
private Integer imageClassCheck;
/**
* 测试前人脸识别验证
*/
private Integer imageTestCheck;
/**
* 活跃度检测开启/关闭
*/
private Integer activityDetection;
/**
* 活跃度检测方式
*/
private Integer activityDetectionMethod;
/**
* 首次播放允许拖曳
*/
private Integer firstDragAllowed;
/**
* 首次播放允许倍速
*/
private Integer firstSpeedAllowed;
/**
* 课时抓拍
*/
private Integer playSnap;
......
......@@ -31,15 +31,13 @@ public class ImageCheckRecordDO extends BaseModel {
private Long classId;
/**
* 试卷id
*/
private Long paperId;
/**
* 成员id
*/
private Long memberId;
/**
* 请求id
*/
private String requestId;
/**
......
......@@ -93,7 +93,7 @@ public class MemberDO extends BaseModel {
/**
* 采集时间
*/
private LocalDateTime checkTime;
private String checkTime;
/**
* 身份证号
......
package com.subsidy.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.subsidy.dto.detection.GetCheckHistoryDTO;
import com.subsidy.dto.detection.VerifyDTO;
import com.subsidy.model.ActivityDetectionDO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.subsidy.vo.activity.GetCheckHistoryVO;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
......@@ -20,6 +21,6 @@ public interface ActivityDetectionService extends IService<ActivityDetectionDO>
String verify(VerifyDTO verifyDTO, HttpServletRequest request);
IPage<ActivityDetectionDO> getCheckHistory(ActivityDetectionDO activityDetectionDO);
IPage<GetCheckHistoryVO> getCheckHistory(GetCheckHistoryDTO getCheckHistoryDTO);
}
......@@ -6,10 +6,12 @@ import com.subsidy.dto.administer.OperatorsDTO;
import com.subsidy.dto.company.AddCompanyDTO;
import com.subsidy.dto.company.GetCompanyMembersDTO;
import com.subsidy.model.CompanyDictDO;
import com.subsidy.model.MemberDO;
import com.subsidy.vo.administer.OperatorsVO;
import com.subsidy.vo.company.CDNStatDetailsVO;
import com.subsidy.vo.company.DataOverviewVO;
import com.subsidy.vo.company.GetAllCompanyVO;
import com.subsidy.vo.company.GetCompanyMembersVO;
import com.subsidy.vo.company.MemberSummaryVO;
import java.util.List;
......@@ -35,4 +37,11 @@ public interface CompanyDictService extends IService<CompanyDictDO> {
IPage<GetCompanyMembersVO> getCompanyMembers(GetCompanyMembersDTO getCompanyMembersDTO);
MemberSummaryVO memberSummary(GetCompanyMembersDTO getCompanyMembersDTO);
DataOverviewVO getCompanyDataOverview();
List<CDNStatDetailsVO> getCDNBandwidthStatDetails();
List<CDNStatDetailsVO> getCDNFluxStatDetails();
}
package com.subsidy.service;
import com.subsidy.dto.image.ImageCheckDTO;
import com.subsidy.model.ImageCheckRecordDO;
import com.baomidou.mybatisplus.extension.service.IService;
......@@ -17,4 +18,6 @@ public interface ImageCheckRecordService extends IService<ImageCheckRecordDO> {
List<ImageCheckRecordDO> getImageCheckHistory(ImageCheckRecordDO imageCheckRecordDO);
String imageCheck(ImageCheckDTO imageCheckDTO)throws Exception;
}
......@@ -43,8 +43,6 @@ public interface MemberService extends IService<MemberDO> {
String updatePassword(MemberDO memberDO);
String updateCheckImage(MemberDO memberDO);
String removeCheckImage(MemberDO memberDO);
List<MyCoursesVO> myCourses(MyCoursesDTO myCoursesDTO);
......
package com.subsidy.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.subsidy.common.configure.ActivityDetectionConfig;
import com.subsidy.common.configure.VODConfig;
import com.subsidy.common.configure.WechatConfig;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.subsidy.dto.detection.GetCheckHistoryDTO;
import com.subsidy.dto.detection.VerifyDTO;
import com.subsidy.model.ActivityDetectionDO;
import com.subsidy.mapper.ActivityDetectionMapper;
import com.subsidy.service.ActivityDetectionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.subsidy.util.ActivityDetectionUtils;
import com.subsidy.util.ConstantUtils;
import com.tencentcloudapi.captcha.v20190722.CaptchaClient;
import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest;
import com.subsidy.vo.activity.GetCheckHistoryVO;
import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
......@@ -33,50 +27,11 @@ import javax.servlet.http.HttpServletRequest;
@Service
public class ActivityDetectionServiceImpl extends ServiceImpl<ActivityDetectionMapper, ActivityDetectionDO> implements ActivityDetectionService {
@Autowired
private ActivityDetectionConfig activityDetectionConfig;
@Autowired
private VODConfig vodConfig;
public String verify(VerifyDTO verifyDTO, HttpServletRequest request){
try{
// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
Credential cred = new Credential(vodConfig.getSecretId(),vodConfig.getSecretKey());
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("captcha.tencentcloudapi.com");
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
CaptchaClient client = new CaptchaClient(cred, "", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeCaptchaResultRequest req = new DescribeCaptchaResultRequest();
req.setCaptchaType(9L);
req.setTicket(verifyDTO.getTicket());
// String ip = request.getHeader("x-forwarded-for");
String ip = request.getHeader( " x-forwarded-for " );
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " WL-Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
req.setUserIp(ip);
req.setRandstr(verifyDTO.getRandStr());
req.setCaptchaAppId(activityDetectionConfig.getCaptchaAppId());
req.setAppSecretKey(activityDetectionConfig.getAppSecretKey());
req.setBusinessId(activityDetectionConfig.getBusinessId());
// 返回的resp是一个DescribeCaptchaResultResponse的实例,与请求对象对应
DescribeCaptchaResultResponse resp = client.DescribeCaptchaResult(req);
DescribeCaptchaResultResponse resp = ActivityDetectionUtils.activityDetection(request,verifyDTO.getRandStr());
// 输出json格式的字符串回包
System.out.println(DescribeCaptchaResultResponse.toJsonString(resp));
ActivityDetectionDO activityDetectionDO = new ActivityDetectionDO();
activityDetectionDO.setClassId(verifyDTO.getClassId());
activityDetectionDO.setMemberId(verifyDTO.getMemberId());
......@@ -90,16 +45,15 @@ public class ActivityDetectionServiceImpl extends ServiceImpl<ActivityDetectionM
this.baseMapper.insert(activityDetectionDO);
return ConstantUtils.FAIL_VERIFY;
}
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
} catch (Exception e) {
// System.out.println(e.toString());
}
return null;
}
public IPage<ActivityDetectionDO> getCheckHistory(ActivityDetectionDO activityDetectionDO){
return null;
public IPage<GetCheckHistoryVO> getCheckHistory(GetCheckHistoryDTO getCheckHistoryDTO){
Page pager = new Page(getCheckHistoryDTO.getPageNum(), getCheckHistoryDTO.getPageSize());
return this.baseMapper.getCheckHistory(pager,getCheckHistoryDTO.getClassId(),getCheckHistoryDTO.getMemberId());
}
}
......@@ -44,7 +44,6 @@ import com.subsidy.model.MemberDepartmentMappingDO;
import com.subsidy.model.OprAdmDictDO;
import com.subsidy.model.PaperDictDO;
import com.subsidy.model.RoleAdministerMappingDO;
import com.subsidy.model.RoleDictDO;
import com.subsidy.model.SignInRecordDO;
import com.subsidy.model.VodDictDO;
import com.subsidy.service.AdministerService;
......@@ -86,12 +85,12 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
......@@ -115,7 +114,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* <p>
* 管理平台用户 服务实现类
......@@ -175,9 +173,6 @@ public class AdministerServiceImpl extends ServiceImpl<AdministerMapper, Adminis
@Autowired
private SignInRecordMapper signInRecordMapper;
//@Autowired
//private MongoTemplate mongoTemplate;
@Autowired
private PaperDictMapper paperDictMapper;
......@@ -380,8 +375,9 @@ public class AdministerServiceImpl extends ServiceImpl<AdministerMapper, Adminis
return ConstantUtils.SET_SUCCESS;
}
@Override
@Cacheable(value = "ResultData", key = "'classId_'+#classDetailDTO.getId()")
public ClassSummaryVO classSummary(ClassDetailDTO classDetailDTO) {
ClassSummaryVO classSummaryVO = new ClassSummaryVO();
//班级人数
......
......@@ -4,35 +4,50 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.subsidy.common.RedisPrefixConstant;
import com.subsidy.common.configure.VODConfig;
import com.subsidy.common.constant.VodConstant;
import com.subsidy.common.exception.HttpException;
import com.subsidy.dto.administer.OperatorsDTO;
import com.subsidy.dto.company.AddCompanyDTO;
import com.subsidy.dto.company.GetCompanyMembersDTO;
import com.subsidy.mapper.AdministerMapper;
import com.subsidy.mapper.ClassDictMapper;
import com.subsidy.mapper.ClassHourDictMapper;
import com.subsidy.mapper.ClassTypeDictMapper;
import com.subsidy.mapper.CompanyDictMapper;
import com.subsidy.mapper.CompanyFieldMappingMapper;
import com.subsidy.mapper.CourseDictMapper;
import com.subsidy.mapper.DepartmentDictMapper;
import com.subsidy.mapper.FieldDictMapper;
import com.subsidy.mapper.JobDictMapper;
import com.subsidy.mapper.MemberMapper;
import com.subsidy.mapper.RankDictMapper;
import com.subsidy.mapper.RoleAdministerMappingMapper;
import com.subsidy.mapper.RotationImgDictMapper;
import com.subsidy.mapper.VodPlayHistoryMapper;
import com.subsidy.mapper.*;
import com.subsidy.model.*;
import com.subsidy.service.CompanyDictService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.subsidy.util.ConstantUtils;
import com.subsidy.util.DateFormatUtil;
import com.subsidy.util.EhCacheUtil;
import com.subsidy.util.VodUtil;
import com.subsidy.vo.administer.OperatorsVO;
import com.subsidy.vo.company.CDNStatDetailsVO;
import com.subsidy.vo.company.DataOverviewVO;
import com.subsidy.vo.company.GetAllCompanyVO;
import com.subsidy.vo.company.GetCompanyMembersVO;
import com.tencentcloudapi.vod.v20180717.models.StatDataItem;
import org.apache.commons.collections.CollectionUtils;
import com.subsidy.vo.company.MemberSummaryVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
......@@ -77,6 +92,21 @@ public class CompanyDictServiceImpl extends ServiceImpl<CompanyDictMapper, Compa
@Autowired
private RotationImgDictMapper rotationImgDictMapper;
@Autowired
private MemberMapper memberMapper;
@Autowired
private ClassDictMapper classDictMapper;
@Autowired
private CourseDictMapper courseDictMapper;
@Autowired
private VodPlayHistoryMapper vodPlayHistoryMapper;
@Autowired
private VODConfig vodConfig;
public IPage<OperatorsVO> operators(OperatorsDTO operatorsDTO) {
Page pager = new Page(operatorsDTO.getPageNum(), operatorsDTO.getPageSize());
......@@ -258,5 +288,129 @@ public class CompanyDictServiceImpl extends ServiceImpl<CompanyDictMapper, Compa
return this.baseMapper.getCompanyMembers(pager,getCompanyMembersDTO.getCompanyId(),getCompanyMembersDTO.getUserName());
}
@Override
public DataOverviewVO getCompanyDataOverview() {
DataOverviewVO dataOverviewVO = new DataOverviewVO();
int companyNum = this.baseMapper.selectCount(new QueryWrapper<>());
/* 机构数量 */
dataOverviewVO.setCompanyNum(companyNum);
List<MemberDO> memberList = memberMapper.selectList(new QueryWrapper<>());
if(CollectionUtils.isNotEmpty(memberList)) {
int realNameNum = (int) memberList.stream().filter(m -> StringUtils.isNotBlank(m.getIdCard())).count();
/* 注册人数 */
dataOverviewVO.setRegistrantsNum(memberList.size());
/* 实名注册人数 */
dataOverviewVO.setRealNameNum(realNameNum);
}
/* 培训项目数量 */
int classNum = classDictMapper.getClassCount();
dataOverviewVO.setClassNum(classNum);
List<CourseDictDO> courseList = courseDictMapper.selectList(new QueryWrapper<>());
if(CollectionUtils.isNotEmpty(courseList)) {
/* 资源数量 */
dataOverviewVO.setCourseNum(courseList.size());
/* 专项资源数量 */
int subsidyCourseNum = (int) courseList.stream().filter(courseDictDO -> StringUtils.isNotBlank(courseDictDO.getCourseType()) &&
courseDictDO.getCourseType().equals("补贴培训")).count();
dataOverviewVO.setSubsidyCourseNum(subsidyCourseNum);
}
/* 累计学习时长(小时) */
double studyTotal = vodPlayHistoryMapper.getStudyTotal();
if(studyTotal > 0) {
dataOverviewVO.setStudyTotal(new BigDecimal(studyTotal).divide(new BigDecimal(Math.pow(60, 2)), 2, BigDecimal.ROUND_UP).doubleValue());
}
/* 专项资源时(小时) */
double subsidyStudyTotal = vodPlayHistoryMapper.getSubsidyStudyTotal();
if(subsidyStudyTotal > 0) {
dataOverviewVO.setSubsidyStudyTotal(new BigDecimal(subsidyStudyTotal).divide(new BigDecimal(Math.pow(60,2)), 2, BigDecimal.ROUND_UP).doubleValue());
}
/* 学习过程记录人次 */
int studyHistoryNum = vodPlayHistoryMapper.getStudyHistoryNum();
dataOverviewVO.setStudyHistoryNum(studyHistoryNum);
return dataOverviewVO;
}
public MemberSummaryVO memberSummary(GetCompanyMembersDTO getCompanyMembersDTO){
MemberSummaryVO memberSummaryVO = new MemberSummaryVO();
//总数
Integer total = memberMapper.selectCount(new QueryWrapper<MemberDO>()
.lambda()
.eq(MemberDO::getCompanyId,getCompanyMembersDTO.getCompanyId()));
memberSummaryVO.setTotal(total);
//短信验证
Integer smsCnt = memberMapper.selectCount(new QueryWrapper<MemberDO>()
.lambda()
.eq(MemberDO::getCompanyId,getCompanyMembersDTO.getCompanyId())
.isNull(MemberDO::getFirstLogin));
memberSummaryVO.setSmsCnt(smsCnt);
memberSummaryVO.setImgCnt(total-smsCnt);
return memberSummaryVO;
}
@Override
public List<CDNStatDetailsVO> getCDNBandwidthStatDetails() {
/*
* 根据今天时间查询七天前的数据
* 先从缓存中获取数据,如果缓存中没有数据,从远程请求中获取, 避免频繁请求
* 缓存28800秒(8小时)失效,重新远程请求更新数据
*/
List<CDNStatDetailsVO> data = new ArrayList<>();
if(EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY) != null) {
return (List<CDNStatDetailsVO>) EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY);
} else {
String startDate =LocalDateTime.now().minusDays(6).withNano(0)+"+08:00";
String endDate = LocalDateTime.now().withNano(0)+"+08:00";
StatDataItem[] statDataItems = VodUtil.DescribeCDNStatDetails(vodConfig, VodConstant.BANDWIDTH ,startDate, endDate);
for (StatDataItem statDataItem : statDataItems) {
CDNStatDetailsVO sd = new CDNStatDetailsVO();
LocalDateTime localDateTime = LocalDateTime.parse(statDataItem.getTime().replace("+08:00",""));
Date date = DateFormatUtil.localDateTimeToDate(localDateTime);
sd.setTime(DateFormatUtil.format(date, DateFormatUtil.FMT_sdf_yMd));
BigDecimal bigDecimal = new BigDecimal(statDataItem.getValue()).divide(new BigDecimal(1000000));
sd.setValue(bigDecimal.setScale(2, BigDecimal.ROUND_UP));
data.add(sd);
}
EhCacheUtil.putEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY, data);
return data;
}
}
@Override
public List<CDNStatDetailsVO> getCDNFluxStatDetails() {
/*
* 根据今天时间查询七天前的数据
* 先从缓存中获取数据,如果缓存中没有数据,从远程请求中获取,避免频繁请求
* 缓存28800秒(8小时)失效,重新远程请求更新数据
*/
List<CDNStatDetailsVO> data = new ArrayList<>();
if(EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY) != null) {
return (List<CDNStatDetailsVO>) EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY);
} else {
String startDate =LocalDateTime.now().minusDays(6).withNano(0)+"+08:00";
String endDate = LocalDateTime.now().withNano(0)+"+08:00";
StatDataItem[] statDataItems = VodUtil.DescribeCDNStatDetails(vodConfig, VodConstant.FLUX ,startDate, endDate);
for (StatDataItem statDataItem : statDataItems) {
CDNStatDetailsVO sd = new CDNStatDetailsVO();
LocalDateTime localDateTime = LocalDateTime.parse(statDataItem.getTime().replace("+08:00",""));
Date date = DateFormatUtil.localDateTimeToDate(localDateTime);
sd.setTime(DateFormatUtil.format(date, DateFormatUtil.FMT_sdf_yMd));
BigDecimal bigDecimal = new BigDecimal(statDataItem.getValue()).divide(new BigDecimal(Math.pow(1000, 3)));
sd.setValue(bigDecimal.setScale(2, BigDecimal.ROUND_UP));
data.add(sd);
}
EhCacheUtil.putEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY, data);
return data;
}
}
}
package com.subsidy.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.google.common.hash.Hashing;
import com.subsidy.common.configure.RestTemplateConfig;
import com.subsidy.common.exception.HttpException;
import com.subsidy.dto.image.ImageCheckDTO;
import com.subsidy.mapper.MemberMapper;
import com.subsidy.model.ImageCheckRecordDO;
import com.subsidy.mapper.ImageCheckRecordMapper;
import com.subsidy.model.MemberDO;
import com.subsidy.service.ImageCheckRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.subsidy.util.ConstantUtils;
import com.subsidy.util.DateFormatUtil;
import com.subsidy.util.ImageCheckUtil;
import com.subsidy.vo.token.*;
import com.subsidy.vo.wechat.AccessTokenVO;
import com.tencentcloudapi.faceid.v20180301.models.GetFaceIdResultResponse;
import com.tencentcloudapi.faceid.v20180301.models.ImageRecognitionResponse;
import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
......@@ -20,12 +42,224 @@ import java.util.List;
@Service
public class ImageCheckRecordServiceImpl extends ServiceImpl<ImageCheckRecordMapper, ImageCheckRecordDO> implements ImageCheckRecordService {
public List<ImageCheckRecordDO> getImageCheckHistory(ImageCheckRecordDO imageCheckRecordDO){
@Autowired
private MemberMapper memberMapper;
@Autowired
private RestTemplateConfig restTemplateConfig;
// public static final String WBAPPID = "IDAaOibN";
// public static final String SECRET= "GD6Z55rHXSlBZB4oxEEowwI5h4IgwUdh0xOOHi6fambXYMFcHuDaBRxtnMx5FVhk";
public static final String WBAPPID = "TIDAbX8x";
public static final String SECRET = "cWAMlQ8Aq7aOad0wrtfJcSpcgksCLFT62qHC4uDHFCGx0SPKqtpt1PungiAKya2M";
public List<ImageCheckRecordDO> getImageCheckHistory(ImageCheckRecordDO imageCheckRecordDO) {
return this.baseMapper.selectList(new QueryWrapper<ImageCheckRecordDO>()
.lambda()
.eq(ImageCheckRecordDO::getClassId,imageCheckRecordDO.getClassId())
.eq(ImageCheckRecordDO::getMemberId,imageCheckRecordDO.getMemberId())
.eq(ImageCheckRecordDO::getClassId, imageCheckRecordDO.getClassId())
.eq(ImageCheckRecordDO::getMemberId, imageCheckRecordDO.getMemberId())
.orderByDesc(ImageCheckRecordDO::getCreateDate));
}
public String imageCheck(ImageCheckDTO imageCheckDTO) throws Exception {
//获取这个学生的基本信息
MemberDO memberDO = memberMapper.selectById(imageCheckDTO.getId());
if (StringUtils.isEmpty(memberDO.getIdCard())) {
throw new HttpException(10025);
}
//获取token
IdCardAccessTokenVO idCardAccessTokenVO = this.accessToken();
//获取signTicket
IdCardTicketsVO idCardTicketsVO = this.signTickets(idCardAccessTokenVO.getAccess_token());
List<String> signList1 = new ArrayList<>();
signList1.add(WBAPPID);
signList1.add("001");
signList1.add(memberDO.getUserName());
signList1.add(memberDO.getIdCard());
signList1.add(memberDO.getId() + "");
signList1.add("1.0.0");
//生成签名
String sign = sign(signList1, idCardTicketsVO.getValue());
System.out.println(sign);
//合作方后台上送身份信息
SendIdCardInfoVO sendIdCardInfoVO = this.sendIdCardInfo("001", memberDO, sign);
//获取 NONCE ticket
IdCardTicketsVO nonceTicket = this.nonceTicket(idCardAccessTokenVO.getAccess_token(), memberDO.getId() + "");
//签名2
List<String> signList2 = new ArrayList<>();
signList2.add(WBAPPID);
signList2.add(memberDO.getId() + "");
signList2.add(imageCheckDTO.getNonce());
signList2.add("1.0.0");
signList2.add(sendIdCardInfoVO.getResult().getH5faceId());
signList2.add(sendIdCardInfoVO.getResult().getOrderNo());
String sign2 = sign(signList2, nonceTicket.getValue());
//启动人脸验证
this.startCheck(imageCheckDTO.getNonce(), sendIdCardInfoVO.getResult(), memberDO.getId() + "", sign2);
//签名3
List<String> signList3 = new ArrayList<>();
signList3.add(WBAPPID);
signList3.add("001");
signList3.add("1.0.0");
signList3.add(imageCheckDTO.getNonce());
String sign3 = sign(signList3,idCardTicketsVO.getValue());
System.out.println(sign3);
//人身核验结果
ResultVO resultVO = this.checkResult("001", imageCheckDTO.getNonce(), sign3);
if (Double.valueOf(resultVO.getSimilarity()) > 80.0) {
return ConstantUtils.SUCCESS_VERIFY;
} else {
return ConstantUtils.FAIL_VERIFY;
}
}
/**
* 获取accessToken
*/
public IdCardAccessTokenVO accessToken() {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/access_token?app_id=" + WBAPPID
+ "&secret=" + SECRET + "&grant_type=client_credential&version=1.0.0";
ResponseEntity<IdCardAccessTokenVO> response = restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, null, IdCardAccessTokenVO.class);
System.out.println(response.getBody().toString());
return response.getBody();
}
/**
* 获取sign_ticket
*/
public IdCardTicketsVO signTickets(String accessToken) {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/api_ticket?app_id=" + WBAPPID + "&access_token=" + accessToken + "&type=SIGN&version=1.0.0";
ResponseEntity<IdCardSignTicketVO> response = restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, null, IdCardSignTicketVO.class);
System.out.println(response.getBody().getTickets());
return response.getBody().getTickets().get(0);
}
/**
* 获取签名
*/
public static String sign(List<String> values, String ticket) { //values传ticket外的其他参数
if (values == null) {
throw new NullPointerException("values is null");
}
values.removeAll(Collections.singleton(null));// remove null
values.add(ticket);
java.util.Collections.sort(values);
StringBuilder sb = new StringBuilder();
for (String s : values) {
sb.append(s);
}
return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase();
}
/**
* 合作方后台上送身份信息 POST请求
*/
public SendIdCardInfoVO sendIdCardInfo(String orderNo, MemberDO memberDO, String sign) {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/server/h5/geth5faceid?orderNo=" + orderNo;
String input = "{\n" +
" \"webankAppId\":\"" + WBAPPID + "\",\n" +
" \"orderNo\":\"" + orderNo + "\",\n" +
" \"name\":\"" + memberDO.getUserName() + "\"," +
" \"idNo\":\"" + memberDO.getIdCard() + "\"," +
" \"userId\":\"" + memberDO.getId() + "\"," +
" \"version\":\"1.0.0\"," +
" \"sign\":\"" + sign + "\"" +
"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ResponseEntity<SendIdCardInfoVO> responseEntity = restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.POST, new HttpEntity<>(input, headers), SendIdCardInfoVO.class);
return responseEntity.getBody();
}
/**
* 获取nonce ticket
*/
public IdCardTicketsVO nonceTicket(String accessToken, String usrId) {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/api_ticket?app_id=" + WBAPPID +
"&access_token=" + accessToken +
"&type=NONCE&version=1.0.0&user_id=" + usrId;
ResponseEntity<IdCardSignTicketVO> response = restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, null, IdCardSignTicketVO.class);
return response.getBody().getTickets().get(0);
}
/**
* 启动 H5 人脸核身
*/
public void startCheck(String nonce, SendResultVO sendResultVO, String userId, String sign) {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/pc/login?webankAppId=" + WBAPPID +
"&version=1.0.0" +
"&nonce=" + nonce +
"&orderNo=" + sendResultVO.getOrderNo() +
"&h5faceId=" + sendResultVO.getH5faceId() +
"&url=" + sendResultVO.getOptimalDomain() +
"&userId=" + userId +
"&sign=" + sign;
restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, null, IdCardSignTicketVO.class);
}
/**
* 人脸核身结果查询 POST
*/
public ResultVO checkResult(String orderNo,String nonce,String sign) {
String url = "https://miniprogram-kyc.tencentcloudapi.com/api/v2/base/queryfacerecord?orderNo="+orderNo;
String input = "{\n" +
" \"appId\":\"" + WBAPPID + "\",\n" +
" \"version\":\"1.0.0\",\n" +
" \"nonce\":\""+nonce+"\"," +
" \"orderNo\":\"" + orderNo + "\"," +
" \"sign\":\"" + sign + "\"," +
" \"getFile\":\"2\"," +
" \"queryVersion\":\"\"" +
"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ResponseEntity<CheckResultVO> responseEntity = restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.POST, new HttpEntity<>(input.getBytes(), headers), CheckResultVO.class);
return responseEntity.getBody().getResultVO();
}
}
......@@ -709,12 +709,6 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, MemberDO> imple
return ConstantUtils.SET_SUCCESS;
}
public String updateCheckImage(MemberDO memberDO) {
memberDO.setCheckTime(LocalDateTime.now());
this.baseMapper.updateById(memberDO);
return ConstantUtils.SET_SUCCESS;
}
public String removeCheckImage(MemberDO memberDO) {
this.baseMapper.removeCheckImage(memberDO.getId());
return ConstantUtils.DELETE_SUCCESS;
......
......@@ -66,9 +66,9 @@ public class VodDictServiceImpl extends ServiceImpl<VodDictMapper, VodDictDO> im
if(null == vod) {
throw new HttpException(18000);
}
this.baseMapper.deleteById(vodDictDO.getId());
VodUtil.deleteMedia(vodDictDO.getVodCode());
this.baseMapper.deleteById(vodDictDO.getId());
VodUtil.deleteMedia(vodConfig, vodDictDO.getVodCode());
}
@Override
......@@ -85,12 +85,13 @@ public class VodDictServiceImpl extends ServiceImpl<VodDictMapper, VodDictDO> im
orderNo = vod.getOrderNo() + 1;
}
}
vodDictDO.setOrderNo(orderNo);
this.baseMapper.insert(vodDictDO);
//测试环境就不转码了
if (env.equals("prod")){
VodUtil.processMedia(vodDictDO.getVodCode());
VodUtil.processMedia(vodConfig, vodDictDO.getVodCode());
}
}
......
package com.subsidy.util;
import com.tencentcloudapi.captcha.v20190722.CaptchaClient;
import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest;
import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import javax.servlet.http.HttpServletRequest;
public class ActivityDetectionUtils {
/**
* 活跃度检测工具类
* @param request
* @param randstr
* @return
* @throws Exception
*/
public static DescribeCaptchaResultResponse activityDetection(HttpServletRequest request, String randstr) throws Exception {
// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
Credential cred = new Credential(ConstantUtils.SECRET_ID, ConstantUtils.SECRET_KEY);
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("captcha.tencentcloudapi.com");
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
CaptchaClient client = new CaptchaClient(cred, "", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeCaptchaResultRequest req = new DescribeCaptchaResultRequest();
req.setCaptchaType(9L);
String ip = IpAddressUtil.getIpAddress(request);
req.setUserIp(ip);
req.setRandstr(randstr);
req.setCaptchaAppId(ConstantUtils.CAPTCHAAPP_ID);
req.setAppSecretKey(ConstantUtils.APP_SECRET_KEY);
req.setBusinessId(ConstantUtils.BUSINESS_ID);
// 返回的resp是一个DescribeCaptchaResultResponse的实例,与请求对象对应
return client.DescribeCaptchaResult(req);
}
}
......@@ -86,4 +86,25 @@ public class ConstantUtils {
public static final String ADMINISTER_TERMINATE = "administer";
/**
* API密钥--微信参数
*/
public static final String SECRET_ID = "AKIDOcePHvZ2C5VeYHQGSO5aqtlNxJQLqfz2";
public static final String SECRET_KEY = "vjHYRmrfDbw0rWxA7oFcj7F8lDPKCm8E";
/**
* 图形验证码
*/
public static final Long CAPTCHAAPP_ID = 2013197365L;
public static final String APP_SECRET_KEY = "04ABoF0ZVuMje8NP84DE5Sg**";
public static final Long BUSINESS_ID = 1L;
/**
* 人脸识别
*/
}
package com.subsidy.util;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.springframework.util.ClassUtils;
/**
* <p>
* Ehcache
* </p>
*
* @author DengMin
* @since 2022/8/1
*/
public class EhCacheUtil {
static CacheManager cacheManager = CacheManager.newInstance(ClassUtils.getDefaultClassLoader().getResource("").getPath()+"ehcache.xml");
/**
* 添加缓存
* @param cacheName
* @param key
* @param value
*/
public static void putEhCache(String cacheName, String key, Object value) {
Cache cache = cacheManager.getCache(cacheName);
Element element = new Element(key, value);
cache.put(element);
}
/**
* 获取缓存数据
* @param cacheName
* @param key
* @return
*/
public static Object getEhCache(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
Element element = cache.get(key);
return element == null ? null : element.getObjectValue();
}
/**
* 删除缓存
* @param cacheName
* @param key
*/
public static void deleteEhCache(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
cache.remove(key);
}
}
package com.subsidy.util;
import com.google.common.hash.Hashing;
import org.apache.commons.codec.Charsets;
import java.util.Collections;
import java.util.List;
/**
* 人脸识别工具类
*/
public class ImageCheckUtil {
/**
* 签名方法
* @param values
* @param ticket
* @return
*/
public static String sign(List<String> values, String ticket) { //values传ticket外的其他参数
if (values == null) {
throw new NullPointerException("values is null");
}
values.removeAll(Collections.singleton(null));// remove null
values.add(ticket); java.util.Collections.sort(values);
StringBuilder sb = new StringBuilder();
for (String s : values) { sb.append(s);
}
return Hashing.sha1().hashString(sb,
Charsets.UTF_8).toString().toUpperCase();
}
}
......@@ -6,21 +6,28 @@ import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.cvm.v20170312.models.DescribeZonesResponse;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.DeleteMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.DescribeCDNUsageDataRequest;
import com.tencentcloudapi.vod.v20180717.models.DescribeCDNUsageDataResponse;
import com.tencentcloudapi.vod.v20180717.models.MediaProcessTaskInput;
import com.tencentcloudapi.vod.v20180717.models.ProcessMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.ProcessMediaResponse;
import com.tencentcloudapi.vod.v20180717.models.StatDataItem;
import com.tencentcloudapi.vod.v20180717.models.TranscodeTaskInput;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* <p>
* 腾讯云 - 云点播API
* </p>
*
* @author DengMin
* @since 2022/8/1
*/
@Component
public class VodUtil {
@Autowired
private static VODConfig vodConfig;
private static String endpoint = "vod.tencentcloudapi.com";
/**
......@@ -28,7 +35,7 @@ public class VodUtil {
* @param vodCode
* @return
*/
public static ProcessMediaResponse processMedia(String vodCode) {
public static ProcessMediaResponse processMedia(VODConfig vodConfig, String vodCode) {
try {
//上传后直接转码
Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey());
......@@ -59,7 +66,7 @@ public class VodUtil {
* 删除腾讯云上原视频
* @param vodCode
*/
public static void deleteMedia(String vodCode) {
public static void deleteMedia(VODConfig vodConfig, String vodCode) {
try {
//删除原视频
Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey());
......@@ -76,6 +83,41 @@ public class VodUtil {
// 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应
client.DeleteMedia(req);
} catch (TencentCloudSDKException e) {
throw new HttpException(99999, e.getMessage());
}
}
/**
* 云点播域名的CDN统计数据
* @param vodConfig
* @param DataType
* @param startTime
* @param endTime
* @return
*/
public static StatDataItem[] DescribeCDNStatDetails(VODConfig vodConfig, String DataType, String startTime, String endTime) {
try {
Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey());
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(endpoint);
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
VodClient client = new VodClient(cred, "", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeCDNUsageDataRequest req = new DescribeCDNUsageDataRequest();
req.setStartTime(startTime);
req.setEndTime(endTime);
req.setDataType(DataType);
// 返回的resp是一个DescribeCDNUsageDataResponse的实例,与请求对象对应
DescribeCDNUsageDataResponse resp = client.DescribeCDNUsageData(req);
// 返回的resp是一个DescribeCDNStatDetailsResponse的实例,与请求对象对应
return resp.getData();
} catch (TencentCloudSDKException e) {
e.printStackTrace();
throw new HttpException(99999, e.getMessage());
}
}
}
......@@ -40,6 +40,10 @@ public class WebSocketUtil implements WebSocketHandler {
@Autowired
private OprMemDictMapper oprMemDictMapper;
private int heartbeatMin = 1; // 断连最小心跳次数
private int heartbeatMax = 3; // 断连最大心跳次数
private int reconnectionSeconds = 60; //每次断连间隔重新连接秒
/**
* 存放建立连接webSocket对象
*/
......@@ -58,14 +62,13 @@ public class WebSocketUtil implements WebSocketHandler {
Long id = Long.valueOf(params.split("=")[1]);
if(null != webSocketMap && webSocketMap.get(id) != null) {
if(webSocketMap.get(id).isOpen()) {
/*
相同账户进行挤号,发送消息给前者WebSocket通知账户已在其他地方登录
*/
/* 相同账户进行挤号,发送消息给WebSocket通知账户已在其他地方登录 */
webSocketMap.get(id).sendMessage(new TextMessage(JSONObject.toJSONString(ResponseData.generateCreatedResponse(1011))));
webSocketMap.get(id).close();
} else {
/*
* 如果上次连接的WebSocket状态是关闭,并且上一次记录时间大于60秒的,则判断为这次登陆是免密码登陆的重新记录上线时间
* 如果上次连接的WebSocket状态是关闭,
* 并且上一次记录时间大于 { heartbeatMax * reconnectionSeconds } 秒(心跳检测机制),则判断为这次登陆是免密码登陆的重新记录上线时间
*/
List<OprMemDictDO> list = oprMemDictMapper.selectList(new QueryWrapper<OprMemDictDO>()
.lambda()
......@@ -74,7 +77,7 @@ public class WebSocketUtil implements WebSocketHandler {
Calendar calendar = Calendar.getInstance();
calendar.setTime(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate()));
calendar.add(Calendar.SECOND,60);
calendar.add(Calendar.SECOND,heartbeatMax * reconnectionSeconds);
if(calendar.getTime().after(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate()))) {
if(list.get(0).getOprType().equals("登出")) {
OprMemDictDO oprMemDictDO = new OprMemDictDO();
......@@ -127,9 +130,6 @@ public class WebSocketUtil implements WebSocketHandler {
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception{
if(null != session) {
/*
断开连接后不会马上判断为下线状态,而是进入60秒的心跳检测机制,如果60秒内没有进行重连,则判断为下线,记录下线时间和状态
*/
if(null != webSocketMap) {
String params = session.getUri().getQuery();
Long id = Long.valueOf(params.split("=")[1]);
......@@ -141,17 +141,19 @@ public class WebSocketUtil implements WebSocketHandler {
}
/**
* 断开连接后60秒后进行判断是否重新连接了,如果没有连接成功则判断为下线
* 断开连接后进行三次心跳验证判断是否重新连接了,如果没有连接成功则判断为下线
*
* @param session
*/
public void heartbeat(WebSocketSession session) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
ScheduledFuture scheduledFuture = service.scheduleAtFixedRate(new Runnable() {
int beatsNum = heartbeatMin;
@SneakyThrows
@Override
public void run() {
if(null != session && !session.isOpen()) {
while (beatsNum > heartbeatMax) {
String params = session.getUri().getQuery();
Long id = Long.valueOf(params.split("=")[1]);
OprMemDictDO oprMemDictDO = new OprMemDictDO();
......@@ -162,8 +164,13 @@ public class WebSocketUtil implements WebSocketHandler {
oprMemDictMapper.insert(oprMemDictDO);
taskMap.get(session.getId()).cancel(true);
}
beatsNum++;
} else if (null != session && session.isOpen()) {
/* 时间段内重新连接了结束验证 */
taskMap.get(session.getId()).cancel(true);
}
}
}, 1, 1, TimeUnit.MINUTES);
}, 0, reconnectionSeconds, TimeUnit.SECONDS);
taskMap.put(session.getId(), scheduledFuture);
}
......
package com.subsidy.vo.activity;
import lombok.Data;
@Data
public class GetCheckHistoryVO {
private Long id;
private String createDate;
private Integer status;
}
package com.subsidy.vo.company;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class CDNStatDetailsVO implements Serializable {
private String time;
private BigDecimal value;
}
package com.subsidy.vo.company;
import lombok.Data;
@Data
public class DataOverviewVO {
/**
* 机构数
*/
private Integer companyNum;
/**
* 注册人数
*/
private Integer registrantsNum;
/**
* 实名制注册人数
*/
private Integer realNameNum;
/**
* 培训项目数量
*/
private Integer classNum;
/**
* 资源数量
*/
private Integer courseNum;
/**
* 学习过程记录人次
*/
private Integer studyHistoryNum;
/**
* 累计学习时长
*/
private Double studyTotal;
/**
* 专项资源数量
*/
private Integer subsidyCourseNum;
/**
* 专项资源时长
*/
private Double subsidyStudyTotal;
}
package com.subsidy.vo.company;
import lombok.Data;
@Data
public class MemberSummaryVO {
private Integer total;
private Integer smsCnt;
private Integer imgCnt;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class CheckResultVO {
private String code;
private String msg;
private String bizSeqNo;
private ResultVO resultVO;
private String transactionTime;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class IdCardAccessTokenVO {
private String code;
private String msg;
private String transactionTime;
private String access_token;
private String expire_time;
private String expire_in;
}
package com.subsidy.vo.token;
import lombok.Data;
import java.util.List;
@Data
public class IdCardSignTicketVO {
private String code;
private String msg;
private String transactionTime;
private List<IdCardTicketsVO> tickets;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class IdCardTicketsVO {
private String value;
private String expire_in;
private String expire_time;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class ResultVO {
private String orderNo;
private String liveRate;
private String similarity;
private String occurredTime;
private String appId;
private String photo;
private String video;
private String bizSeqNo;
private String sdkVersion;
private String trtcFlag;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class SendIdCardInfoVO {
private String code;
private String msg;
private String bizSeqNo;
private SendResultVO result;
private String transactionTime;
}
package com.subsidy.vo.token;
import lombok.Data;
@Data
public class SendResultVO {
private String bizSeqNo;
private String transactionTime;
private String orderNo;
private String h5faceId;
private String optimalDomain;
private Boolean success;
}
......@@ -2,7 +2,7 @@
spring.server.port=23457
# 数据源配置
spring.datasource.url=jdbc:mysql://47.97.19.66:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.url=jdbc:mysql://116.62.57.92:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
#spring.datasource.url=jdbc:mysql://rm-uf6rab73w0qg843opxo.mysql.rds.aliyuncs.com:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
......
......@@ -34,6 +34,9 @@ mybatis-plus.global-config.db-config.logic-delete-value=NOW()
mybatis-plus.global-config.db-config.logic-not-delete-value=NULL
#日志配置
logging.config=classpath:logback-spring.xml
#ehcache缓存配置
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml
# 阿里云短信
sms.product=Dysmsapi
sms.domain=dysmsapi.aliyuncs.com
......@@ -69,9 +72,3 @@ wechat:
#pro
appId: wx5e1ecb9c9bd33451
appSecret: 4f5e1abb6fb4f68f5273820b6295ec6b
#活体检测配置
activity.captchaAppId: 2013197365
activity.appSecretKey: 04ABoF0ZVuMje8NP84DE5Sg**
activity.businessId: 1
\ No newline at end of file
......@@ -17,6 +17,7 @@ meishu.code-message[10021]=密码输入错误,您还可以输入1次密码
meishu.code-message[10022]=密码输入错误,您还可以输入2次密码
meishu.code-message[10023]=密码输入错误,您还可以输入3次密码
meishu.code-message[10024]=密码输入错误,您还可以输入4次密码
meishu.code-message[10025]=身份证识别错误
meishu.code-message[20001]=该课程已存在
......
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="java.io.tmpdir" />
<defaultCache eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="true"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU" />
<!--
maxElementsInMemory 缓存最大个数,若放入Cache中的元素超过这个数值,则有以下两种情况
1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中
2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素
eternal 缓存中对象是否永久有效
timeToIdleSeconds 缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,默认值是0表示可闲置时间无穷大,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除
timeToLiveSeconds 缓存数据的总的存活时间(单位:秒),仅当eternal=false时使用,从创建开始计时,失效结束
overflowToDisk 内存不足时,是否启用磁盘缓存
diskPersistent 是否缓存虚拟机重启期数据
maxBytesLocalHeap 限制堆内存字节大小
-->
<!-- 云点播数据统计缓存 -->
<cache name="CDNStatDetails"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="28800"
memoryStoreEvictionPolicy="LRU"/>
<!-- 普通数据缓存 -->
<cache name="ResultData"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="7200"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
\ No newline at end of file
......@@ -21,4 +21,17 @@
id, class_id, member_id, status
</sql>
<select id="getCheckHistory" resultType="com.subsidy.vo.activity.GetCheckHistoryVO">
SELECT
t.id,
t.`status`,
t.create_date
FROM
activity_detection t
WHERE
t.delete_date IS NULL
AND t.class_id = #{classId}
AND t.member_id = #{memberId}
</select>
</mapper>
......@@ -169,4 +169,16 @@
AND cd.delete_date IS NULL
AND d.delete_date IS NULL
</select>
<select id="getClassCount" resultType="java.lang.Integer">
SELECT
count(t1.id)
FROM
class_dict t1
LEFT JOIN course_dict t2 ON t2.id = t1.course_id
WHERE
t2.course_type = "补贴培训"
AND t1.delete_date IS NULL
AND t2.delete_date IS NULL
</select>
</mapper>
......@@ -93,13 +93,11 @@
count( 1 ) AS cnt
FROM
course_content t
LEFT JOIN content_vod_mapping t3 ON t3.content_id = t.id
LEFT JOIN vod_dict t2 ON t.id = t3.vod_id
LEFT JOIN content_vod_mapping t2 ON t.id = t2.content_id
WHERE
t.delete_date IS NULL
AND t2.delete_date IS NULL
AND t3.delete_date IS NULL
AND t2.id IS NOT NULL
and t2.id is not null
GROUP BY
t.course_id
) t4 ON t3.id = t4.course_id
......
......@@ -398,4 +398,36 @@
t.create_date
</select>
<select id="getStudyTotal" resultType="java.lang.Double">
SELECT
sum( play_length )
FROM
vod_play_history
WHERE
delete_date IS NULL
</select>
<select id="getSubsidyStudyTotal" resultType="java.lang.Double">
SELECT
sum( t1.play_length )
FROM
vod_play_history t1
LEFT JOIN class_dict t2 ON t2.id = t1.class_id
LEFT JOIN course_dict t3 ON t3.id = t2.course_id
WHERE
t3.course_type = "补贴培训"
AND t1.delete_date IS NULL
AND t2.delete_date IS NULL
AND t3.delete_date IS NULL
</select>
<select id="getStudyHistoryNum" resultType="java.lang.Integer">
SELECT
count(DISTINCT member_id)
FROM
vod_play_history
WHERE
delete_date IS NULL
</select>
</mapper>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!