将统计数据抽成公共方法, 让小程序和后台管理系统都能调用

This commit is contained in:
mirage 2026-02-26 10:34:22 +08:00
parent c3a8f590e8
commit 80722947ff
3 changed files with 229 additions and 200 deletions

View File

@ -4,21 +4,14 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.mdd.admin.service.IIndexService; import com.mdd.admin.service.IIndexService;
import com.mdd.common.config.GlobalConfig; import com.mdd.common.config.GlobalConfig;
import com.mdd.common.entity.StudentInfo; import com.mdd.common.service.EnrollmentStaticService;
import com.mdd.common.entity.Teacher;
import com.mdd.common.mapper.StudentInfoMapper;
import com.mdd.common.mapper.TeacherMapper;
import com.mdd.common.util.ConfigUtils; import com.mdd.common.util.ConfigUtils;
import com.mdd.common.util.ListUtils; import com.mdd.common.util.ListUtils;
import com.mdd.common.util.TimeUtils;
import com.mdd.common.util.UrlUtils; import com.mdd.common.util.UrlUtils;
import com.mdd.common.util.YmlUtils; import com.mdd.common.util.YmlUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
/** /**
@ -28,18 +21,15 @@ import java.util.*;
public class IndexServiceImpl implements IIndexService { public class IndexServiceImpl implements IIndexService {
@Resource @Resource
private StudentInfoMapper studentInfoMapper; private EnrollmentStaticService enrollmentStaticService;
@Resource
private TeacherMapper teacherMapper;
/** /**
* 控制台数据 * 控制台数据
* *
* @author fzr
* @param teacherId 招生老师ID可选 * @param teacherId 招生老师ID可选
* @param rangeType 时间区间类型day / week / month可选默认 week * @param rangeType 时间区间类型day / week / month可选默认 week
* @return Map<String, Object> * @return Map<String, Object>
* @author fzr
*/ */
@Override @Override
public Map<String, Object> index(Integer teacherId, String rangeType) { public Map<String, Object> index(Integer teacherId, String rangeType) {
@ -58,11 +48,11 @@ public class IndexServiceImpl implements IIndexService {
console.put("version", version); console.put("version", version);
// 招生统计数据 // 招生统计数据
Map<String, Object> enrollmentStats = buildEnrollmentStats(); Map<String, Object> enrollmentStats = enrollmentStaticService.buildEnrollmentStats();
console.put("today", enrollmentStats); console.put("today", enrollmentStats);
// 招生趋势数据带筛选条件 // 招生趋势数据带筛选条件
Map<String, Object> enrollmentTrend = buildEnrollmentTrend(teacherId, rangeType); Map<String, Object> enrollmentTrend = enrollmentStaticService.buildEnrollmentTrend(teacherId, rangeType);
console.put("enrollmentTrend", enrollmentTrend); console.put("enrollmentTrend", enrollmentTrend);
// 常用功能菜单 // 常用功能菜单
@ -121,192 +111,11 @@ public class IndexServiceImpl implements IIndexService {
return console; return console;
} }
/**
* 构建招生统计数据
* - 总招生数量
* - 今日招生数量
* - 本周招生数量
* - 本月招生数量
*
* 招生数量定义student_status = 0 1 的学生数量
*/
private Map<String, Object> buildEnrollmentStats() {
Map<String, Object> stats = new LinkedHashMap<>();
// 当前时间
Date now = new Date();
stats.put("time", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(now));
// 总招生数量所有时间
long totalCount = studentInfoMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<StudentInfo>()
.in("student_status", 0, 1)
.isNull("delete_time")
);
// 今日本周本月时间范围
LocalDate today = LocalDate.now();
Date todayStart = toDate(today.atStartOfDay());
Date tomorrowStart = toDate(today.plusDays(1).atStartOfDay());
LocalDate weekStartDate = today.minusDays(6); // 最近7天
Date weekStart = toDate(weekStartDate.atStartOfDay());
LocalDate monthStartDate = today.minusDays(29); // 最近30天
Date monthStart = toDate(monthStartDate.atStartOfDay());
long todayCount = countEnrollmentInRange(todayStart, tomorrowStart);
long weekCount = countEnrollmentInRange(weekStart, tomorrowStart);
long monthCount = countEnrollmentInRange(monthStart, tomorrowStart);
stats.put("total_enroll_count", totalCount);
stats.put("today_enroll_count", todayCount);
stats.put("week_enroll_count", weekCount);
stats.put("month_enroll_count", monthCount);
return stats;
}
/**
* 计算时间区间内的招生数量 pre_registration_time 筛选
*/
private long countEnrollmentInRange(Date startTime, Date endTime) {
return studentInfoMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<StudentInfo>()
.in("student_status", 0, 1)
.isNull("delete_time")
.isNotNull("pre_registration_time")
.ge("pre_registration_time", startTime)
.lt("pre_registration_time", endTime)
);
}
/**
* 构建招生趋势数据
*
* @param teacherId 招生老师ID为空则统计所有老师
* @param rangeType 时间区间类型day / week / month
*/
private Map<String, Object> buildEnrollmentTrend(Integer teacherId, String rangeType) {
Map<String, Object> result = new LinkedHashMap<>();
if (rangeType == null || rangeType.trim().isEmpty()) {
rangeType = "week";
}
LocalDate today = LocalDate.now();
LocalDate startDate;
switch (rangeType) {
case "day":
startDate = today;
break;
case "month":
startDate = today.minusDays(29);
break;
case "week":
default:
startDate = today.minusDays(6);
break;
}
LocalDate endDate = today;
Date startTime = toDate(startDate.atStartOfDay());
Date endTime = toDate(endDate.plusDays(1).atStartOfDay());
// 生成日期列表
List<String> dateList = new ArrayList<>();
Map<String, Integer> dateIndexMap = new LinkedHashMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
int idx = 0;
for (LocalDate d = startDate; !d.isAfter(endDate); d = d.plusDays(1)) {
String dateStr = d.format(formatter);
dateList.add(dateStr);
dateIndexMap.put(dateStr, idx++);
}
// 查询数据库中的统计数据按日期 + 招生老师分组
List<Map<String, Object>> rows = studentInfoMapper.selectEnrollmentTrend(startTime, endTime, teacherId);
// 收集涉及到的老师ID
Set<Integer> teacherIds = new LinkedHashSet<>();
for (Map<String, Object> row : rows) {
Object tIdObj = row.get("teacherId");
if (tIdObj != null) {
teacherIds.add(((Number) tIdObj).intValue());
}
}
Map<Integer, String> teacherNameMap = new LinkedHashMap<>();
if (!teacherIds.isEmpty()) {
List<Teacher> teachers = teacherMapper.selectBatchIds(teacherIds);
for (Teacher t : teachers) {
teacherNameMap.put(t.getTeacherId(), t.getTeacherName());
}
}
// 构建每个老师的时间序列数据
Map<Integer, List<Long>> teacherSeriesMap = new LinkedHashMap<>();
for (Integer tId : teacherIds) {
List<Long> initList = new ArrayList<>();
for (int i = 0; i < dateList.size(); i++) {
initList.add(0L);
}
teacherSeriesMap.put(tId, initList);
}
for (Map<String, Object> row : rows) {
Object dateObj = row.get("statDate");
Object tIdObj = row.get("teacherId");
Object countObj = row.get("enrollCount");
if (dateObj == null || tIdObj == null || countObj == null) {
continue;
}
String dateStr = String.valueOf(dateObj);
Integer tId = ((Number) tIdObj).intValue();
Integer index = dateIndexMap.get(dateStr);
if (index == null) {
continue;
}
List<Long> dataList = teacherSeriesMap.get(tId);
if (dataList == null) {
dataList = new ArrayList<>();
for (int i = 0; i < dateList.size(); i++) {
dataList.add(0L);
}
teacherSeriesMap.put(tId, dataList);
}
long count = ((Number) countObj).longValue();
dataList.set(index, count);
}
// 组装返回给前端的 list 数据
JSONArray seriesList = new JSONArray();
for (Map.Entry<Integer, List<Long>> entry : teacherSeriesMap.entrySet()) {
Integer tId = entry.getKey();
List<Long> data = entry.getValue();
JSONObject item = new JSONObject();
item.put("teacherId", tId);
item.put("name", teacherNameMap.getOrDefault(tId, "未知老师"));
item.put("data", data);
seriesList.add(item);
}
result.put("date", dateList);
result.put("list", seriesList);
result.put("rangeType", rangeType);
return result;
}
private Date toDate(java.time.LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/** /**
* 公共配置 * 公共配置
* *
* @author fzr
* @return Map<String, Object> * @return Map<String, Object>
* @author fzr
*/ */
@Override @Override
public Map<String, Object> config() { public Map<String, Object> config() {

View File

@ -0,0 +1,204 @@
package com.mdd.common.service;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.mdd.common.entity.StudentInfo;
import com.mdd.common.entity.Teacher;
import com.mdd.common.mapper.StudentInfoMapper;
import com.mdd.common.mapper.TeacherMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Service
public class EnrollmentStaticService {
@Resource
private StudentInfoMapper studentInfoMapper;
@Resource
private TeacherMapper teacherMapper;
/**
* 构建招生统计数据
* <p>- 总招生数量
* <p>- 今日招生数量
* <p>- 本周招生数量
* <p>- 本月招生数量
* 招生数量定义student_status = 0 1 的学生数量
*/
public Map<String, Object> buildEnrollmentStats() {
Map<String, Object> stats = new LinkedHashMap<>();
// 当前时间
Date now = new Date();
stats.put("time", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(now));
// 总招生数量所有时间
long totalCount = studentInfoMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<StudentInfo>()
.in("student_status", 0, 1)
.isNull("delete_time")
);
// 今日本周本月时间范围
LocalDate today = LocalDate.now();
Date todayStart = toDate(today.atStartOfDay());
Date tomorrowStart = toDate(today.plusDays(1).atStartOfDay());
LocalDate weekStartDate = today.minusDays(6); // 最近7天
Date weekStart = toDate(weekStartDate.atStartOfDay());
LocalDate monthStartDate = today.minusDays(29); // 最近30天
Date monthStart = toDate(monthStartDate.atStartOfDay());
long todayCount = countEnrollmentInRange(todayStart, tomorrowStart);
long weekCount = countEnrollmentInRange(weekStart, tomorrowStart);
long monthCount = countEnrollmentInRange(monthStart, tomorrowStart);
stats.put("total_enroll_count", totalCount);
stats.put("today_enroll_count", todayCount);
stats.put("week_enroll_count", weekCount);
stats.put("month_enroll_count", monthCount);
return stats;
}
/**
* 构建招生趋势数据
*
* @param teacherId 招生老师ID为空则统计所有老师
* @param rangeType 时间区间类型day / week / month
*/
public Map<String, Object> buildEnrollmentTrend(Integer teacherId, String rangeType) {
Map<String, Object> result = new LinkedHashMap<>();
if (rangeType == null || rangeType.trim().isEmpty()) {
rangeType = "week";
}
LocalDate today = LocalDate.now();
LocalDate startDate;
switch (rangeType) {
case "day":
startDate = today;
break;
case "month":
startDate = today.minusDays(29);
break;
case "week":
default:
startDate = today.minusDays(6);
break;
}
LocalDate endDate = today;
Date startTime = toDate(startDate.atStartOfDay());
Date endTime = toDate(endDate.plusDays(1).atStartOfDay());
// 生成日期列表
List<String> dateList = new ArrayList<>();
Map<String, Integer> dateIndexMap = new LinkedHashMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
int idx = 0;
for (LocalDate d = startDate; !d.isAfter(endDate); d = d.plusDays(1)) {
String dateStr = d.format(formatter);
dateList.add(dateStr);
dateIndexMap.put(dateStr, idx++);
}
// 查询数据库中的统计数据按日期 + 招生老师分组
List<Map<String, Object>> rows = studentInfoMapper.selectEnrollmentTrend(startTime, endTime, teacherId);
// 收集涉及到的老师ID
Set<Integer> teacherIds = new LinkedHashSet<>();
for (Map<String, Object> row : rows) {
Object tIdObj = row.get("teacherId");
if (tIdObj != null) {
teacherIds.add(((Number) tIdObj).intValue());
}
}
Map<Integer, String> teacherNameMap = new LinkedHashMap<>();
if (!teacherIds.isEmpty()) {
List<Teacher> teachers = teacherMapper.selectBatchIds(teacherIds);
for (Teacher t : teachers) {
teacherNameMap.put(t.getTeacherId(), t.getTeacherName());
}
}
// 构建每个老师的时间序列数据
Map<Integer, List<Long>> teacherSeriesMap = new LinkedHashMap<>();
for (Integer tId : teacherIds) {
List<Long> initList = new ArrayList<>();
for (int i = 0; i < dateList.size(); i++) {
initList.add(0L);
}
teacherSeriesMap.put(tId, initList);
}
for (Map<String, Object> row : rows) {
Object dateObj = row.get("statDate");
Object tIdObj = row.get("teacherId");
Object countObj = row.get("enrollCount");
if (dateObj == null || tIdObj == null || countObj == null) {
continue;
}
String dateStr = String.valueOf(dateObj);
Integer tId = ((Number) tIdObj).intValue();
Integer index = dateIndexMap.get(dateStr);
if (index == null) {
continue;
}
List<Long> dataList = teacherSeriesMap.get(tId);
if (dataList == null) {
dataList = new ArrayList<>();
for (int i = 0; i < dateList.size(); i++) {
dataList.add(0L);
}
teacherSeriesMap.put(tId, dataList);
}
long count = ((Number) countObj).longValue();
dataList.set(index, count);
}
// 组装返回给前端的 list 数据
JSONArray seriesList = new JSONArray();
for (Map.Entry<Integer, List<Long>> entry : teacherSeriesMap.entrySet()) {
Integer tId = entry.getKey();
List<Long> data = entry.getValue();
JSONObject item = new JSONObject();
item.put("teacherId", tId);
item.put("name", teacherNameMap.getOrDefault(tId, "未知老师"));
item.put("data", data);
seriesList.add(item);
}
result.put("date", dateList);
result.put("list", seriesList);
result.put("rangeType", rangeType);
return result;
}
private Date toDate(java.time.LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 计算时间区间内的招生数量 pre_registration_time 筛选
*/
private long countEnrollmentInRange(Date startTime, Date endTime) {
return studentInfoMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<StudentInfo>()
.in("student_status", 0, 1)
.isNull("delete_time")
.isNotNull("pre_registration_time")
.ge("pre_registration_time", startTime)
.lt("pre_registration_time", endTime)
);
}
}

View File

@ -1,6 +1,7 @@
package com.mdd.front.controller; package com.mdd.front.controller;
import com.mdd.common.core.AjaxResult; import com.mdd.common.core.AjaxResult;
import com.mdd.common.service.EnrollmentStaticService;
import com.mdd.front.service.IStudentInfoService; import com.mdd.front.service.IStudentInfoService;
import com.mdd.front.validate.student.PreRegistrationStudentInfoValidate; import com.mdd.front.validate.student.PreRegistrationStudentInfoValidate;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@ -9,6 +10,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Map;
@RestController @RestController
@RequestMapping("frontapi/student") @RequestMapping("frontapi/student")
@ -16,11 +18,25 @@ import javax.annotation.Resource;
public class StudentInfoController { public class StudentInfoController {
@Resource @Resource
private IStudentInfoService IStudentInfoService; private IStudentInfoService iStudentInfoService;
@Resource
private EnrollmentStaticService enrollmentStaticService;
@PostMapping("/add") @PostMapping("/add")
@ApiOperation(value = "新增预报名学生信息") @ApiOperation(value = "新增预报名学生信息")
public AjaxResult<Object> addPreRegistrationStudentInfo(@Validated @RequestBody PreRegistrationStudentInfoValidate studentInfoValidate) { public AjaxResult<Object> addPreRegistrationStudentInfo(@Validated @RequestBody PreRegistrationStudentInfoValidate studentInfoValidate) {
return IStudentInfoService.add(studentInfoValidate); return iStudentInfoService.add(studentInfoValidate);
}
@PostMapping("/enrollmentStatistical")
@ApiOperation(value = "招生统计数据")
public AjaxResult<Map<String, Object>> buildEnrollmentStatistical() {
return AjaxResult.success(enrollmentStaticService.buildEnrollmentStats());
}
@GetMapping("/enrollmentTrend")
@ApiOperation(value = "招生趋势数据(带筛选条件)")
public AjaxResult<Map<String, Object>> buildEnrollmentTrend(@RequestParam("teacherId") Integer teacherId, @RequestParam("rangeType") String rangeType) {
return AjaxResult.success(enrollmentStaticService.buildEnrollmentTrend(teacherId, rangeType));
} }
} }