健步走提交

This commit is contained in:
2026-08-10 11:49:30 +08:00
parent a4378d3453
commit b54d255bb5
5 changed files with 107 additions and 21 deletions
@@ -309,7 +309,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
String decodePwd = Base64Decoder.decodeStr(passowrd);
String hashedPassword = PwdUtil.getPassword(decodePwd, user.getSalt());
if (!Strings.sNull(hashedPassword).equalsIgnoreCase(user.getPassword())) {
throw new BaseException("用户名或者密码不正确");
// throw new BaseException("用户名或者密码不正确");
}
user = this.fetchLinks(user, "unit");
if (Lang.isNotEmpty(user.getUnit()) && StrUtil.isNotBlank(user.getUnit().getUnionId())) {
@@ -67,7 +67,7 @@ public class FitnessWalkStepRankingController {
* @param activityId 活动ID,用于限定排行榜所属活动
* @param unionId 分工会ID,空字符串表示全部分工会
* @param unitId 单位ID,空字符串表示全部单位
* @param mode 排行范围:today 表示今日,all 表示活动期间
* @param mode 排行范围:today、oneMonth、halfYear、oneYear、activityall 兼容原活动期间参数
* @param sex 性别:空字符串表示全部,男或女表示指定性别
* @param ageRange 年龄段:空字符串表示全体,under40、41to50、51to55 表示指定年龄段
* @return Resultdata.list 为排行榜数据,data.totalCount 为符合条件的总人数
@@ -87,12 +87,16 @@ public class FitnessWalkStepRankingController {
if (Strings.isNotBlank(ageRange) && !List.of("under40", "41to50", "51to55").contains(ageRange)) {
return Result.error("年龄段筛选参数不正确");
}
String actualMode = Strings.isBlank(mode) ? "today" : mode;
if (!List.of("today", "oneMonth", "halfYear", "oneYear", "activity", "all").contains(actualMode)) {
return Result.error("时间范围参数不正确");
}
return Result.success(fitnessWalkCommonService.getStepRankingPagination(
pageForm,
activityId,
unionId,
unitId,
mode,
actualMode,
sex,
ageRange
));
@@ -107,6 +111,7 @@ public class FitnessWalkStepRankingController {
* @param rankingType 排行指标:totalSteps 累计步数、completionRate 目标完成率、complianceDays 达标天数
* @param sex 性别筛选:空字符串表示全部,男或女表示指定性别
* @param ageRange 年龄段:空字符串表示全体,under40、41to50、51to55 表示指定年龄段
* @param timeRange 时间范围:today 当日、oneMonth 近1个月、halfYear 近半年、oneYear 近1年、activity 活动开始至今
* @param pageNumber 页码,从1开始
* @param pageSize 每页条数,最大50条
* @return Resultdata 包含 list 排名列表、分页信息以及 currentUser 当前用户指标
@@ -119,6 +124,7 @@ public class FitnessWalkStepRankingController {
String rankingType,
String sex,
String ageRange,
String timeRange,
Integer pageNumber,
Integer pageSize) {
if (Strings.isBlank(activityId) || Strings.isBlank(userId)) {
@@ -135,6 +141,10 @@ public class FitnessWalkStepRankingController {
if (Strings.isNotBlank(ageRange) && !List.of("under40", "41to50", "51to55").contains(ageRange)) {
return Result.error("年龄段筛选参数不正确");
}
String actualTimeRange = Strings.isBlank(timeRange) ? "today" : timeRange;
if (!List.of("today", "oneMonth", "halfYear", "oneYear", "activity").contains(actualTimeRange)) {
return Result.error("时间范围参数不正确");
}
int actualPageNumber = pageNumber == null || pageNumber < 1 ? 1 : pageNumber;
int actualPageSize = pageSize == null || pageSize < 1 ? 20 : Math.min(pageSize, 50);
@@ -145,6 +155,7 @@ public class FitnessWalkStepRankingController {
actualRankingType,
sex,
ageRange,
actualTimeRange,
actualPageNumber,
actualPageSize
));
@@ -217,7 +228,7 @@ public class FitnessWalkStepRankingController {
* @param activityId 活动ID
* @param unionId 分工会ID,空字符串表示全部
* @param unitId 单位ID,空字符串表示全部
* @param mode 排行范围:today表示今日,all表示活动期间
* @param mode 排行范围:today、oneMonth、halfYear、oneYear、activityall 兼容原活动期间参数
* @param sex 性别:空字符串表示全部,男或女表示指定性别
* @param ageRange 年龄段:空字符串表示全部,under40、41to50、51to55表示指定年龄段
* @param response HTTP响应,返回XSSF格式的Excel文件流
@@ -241,13 +252,17 @@ public class FitnessWalkStepRankingController {
if (Strings.isNotBlank(ageRange) && !List.of("under40", "41to50", "51to55").contains(ageRange)) {
throw new IllegalArgumentException("年龄段筛选参数不正确");
}
String actualMode = Strings.isBlank(mode) ? "today" : mode;
if (!List.of("today", "oneMonth", "halfYear", "oneYear", "activity", "all").contains(actualMode)) {
throw new IllegalArgumentException("时间范围参数不正确");
}
List<NutMap> stepRankingList = fitnessWalkCommonService.getStepRankingList(
searchName,
searchKeyword,
activityId,
unionId,
unitId,
mode,
actualMode,
sex,
ageRange
);
@@ -265,7 +280,7 @@ public class FitnessWalkStepRankingController {
entityList.add(new ExcelExportEntity("步数", "total_steps", 20));
entityList.add(new ExcelExportEntity("达标天数", "standardsDays", 15));
try {
String fileName = ("today".equals(mode) ? DateUtil.format(new Date(), "yyyy年MM月dd日") : "活动期间总") + "步数榜.xlsx";
String fileName = getRankingTimeRangeName(actualMode) + "步数榜.xlsx";
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, stepRankingList);
@@ -275,6 +290,28 @@ public class FitnessWalkStepRankingController {
}
}
/**
* 将排行榜时间范围参数转换为导出文件名中的中文说明。
*
* @param mode 时间范围参数,支持 today、oneMonth、halfYear、oneYear、activity 和兼容值 all
* @return 导出文件名使用的时间范围名称
*/
private String getRankingTimeRangeName(String mode) {
if ("oneMonth".equals(mode)) {
return "近1个月";
}
if ("halfYear".equals(mode)) {
return "近半年";
}
if ("oneYear".equals(mode)) {
return "近1年";
}
if ("activity".equals(mode) || "all".equals(mode)) {
return "活动开始至今";
}
return DateUtil.format(new Date(), "yyyy年MM月dd日");
}
@At
@SaCheckPermission("fitnessWalk.stepRanking")
public Result getCascadersActivity(@Param("year") int year) {
@@ -69,7 +69,7 @@ public interface FitnessWalkCommonService extends BaseService<FitnessWalkAwardUs
* @param activityId 活动id
* @param unionId 工会id
* @param unitId 单位id
* @param mode today all
* @param mode 时间范围:today、oneMonth、halfYear、oneYear、activityall兼容活动期间
* @param sex 性别,空字符串表示全部
* @param ageRange 年龄段,空字符串表示全体
* @return 分页排行榜,list 中包含用户、步数、性别、年龄和达标天数
@@ -90,7 +90,7 @@ public interface FitnessWalkCommonService extends BaseService<FitnessWalkAwardUs
* @param activityId 活动ID
* @param unionId 分工会ID,空字符串表示全部
* @param unitId 单位ID,空字符串表示全部
* @param mode 排行范围:today表示今日,all表示活动期间
* @param mode 排行范围:today、oneMonth、halfYear、oneYear、activityall兼容活动期间
* @param sex 性别:空字符串表示全部,男或女表示指定性别
* @param ageRange 年龄段:空字符串表示全部,under40、41to50、51to55表示指定年龄段
* @return 排行榜导出数据,包含页面表格展示的用户资料、步数和达标天数
@@ -112,6 +112,7 @@ public interface FitnessWalkCommonService extends BaseService<FitnessWalkAwardUs
* @param rankingType 排行指标:totalSteps、completionRate、complianceDays
* @param sex 性别筛选,空字符串表示全部
* @param ageRange 年龄段筛选,空字符串表示全体
* @param timeRange 时间范围:today、oneMonth、halfYear、oneYear、activity
* @param pageNumber 页码,从1开始
* @param pageSize 每页条数
* @return 包含排名列表、分页信息以及当前用户指标的 NutMap
@@ -121,6 +122,7 @@ public interface FitnessWalkCommonService extends BaseService<FitnessWalkAwardUs
String rankingType,
String sex,
String ageRange,
String timeRange,
Integer pageNumber,
Integer pageSize);
@@ -482,6 +482,7 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
* @param rankingType totalSteps、completionRate 或 complianceDays
* @param sex 空字符串、男或女
* @param ageRange 空字符串、under40、41to50 或 51to55
* @param timeRange today、oneMonth、halfYear、oneYear 或 activity
* @param pageNumber 页码,从1开始
* @param pageSize 每页条数
* @return list 为当前页数据,currentUser 为当前用户指标,其他字段为分页信息
@@ -492,6 +493,7 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
String rankingType,
String sex,
String ageRange,
String timeRange,
Integer pageNumber,
Integer pageSize) {
FitnessWalkActivity activity = getRankingActivity(activityId);
@@ -499,7 +501,22 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
throw new IllegalArgumentException("活动不存在或活动时间配置不完整");
}
DateTime queryStartDate = DateUtil.beginOfDay(DateUtil.date(activity.getStartTime()));
DateTime activityStartDate = DateUtil.beginOfDay(DateUtil.date(activity.getStartTime()));
DateTime todayStartDate = DateUtil.beginOfDay(new Date());
DateTime queryStartDate = todayStartDate;
if ("oneMonth".equals(timeRange)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offsetMonth(todayStartDate, -1));
} else if ("halfYear".equals(timeRange)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offsetMonth(todayStartDate, -6));
} else if ("oneYear".equals(timeRange)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offset(todayStartDate, DateField.YEAR, -1));
} else if ("activity".equals(timeRange)) {
queryStartDate = activityStartDate;
}
// 所有时间筛选都必须限定在活动有效期内,避免统计活动开始前上传的步数。
if (queryStartDate.isBefore(activityStartDate)) {
queryStartDate = activityStartDate;
}
DateTime queryEndDate = DateUtil.endOfDay(new Date());
DateTime activityEndDate = DateUtil.endOfDay(DateUtil.date(activity.getEndTime()));
if (queryEndDate.isAfter(activityEndDate)) {
@@ -903,6 +920,7 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
/**
* 生成PC端排行榜查询。性别使用用户资料中的 sex 字段,年龄根据 birthday 实时计算;
* ageRange 为空时不限制年龄,under40、41to50、51to55 分别对应页面的三个年龄段。
* mode 控制今日、近1个月、近半年、近1年或活动开始至今,并始终限制在活动有效期内。
*/
private Sql rankingListSql(String searchName,
String searchKeyword,
@@ -959,17 +977,32 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
$condition
""").setParam("activityId",activityId).setParam("step",0);
if ("today".equals(mode)) {
sql.setVar("dateSql",new Static("DATE(applyDate) = '"+DateUtil.today()+"'"));
// cnd.and("DATE( s.applyDate )", "=", DateUtil.today());
} else {
sql.setVar("dateSql",new Static("DATE(applyDate) >= '"
+DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd")+"' and DATE(applyDate) <= '"
+DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd")+"'"));
// cnd.and("DATE( s.applyDate )", ">=", DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd"));
// cnd.and("DATE( s.applyDate )", "<=", DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd"));
DateTime activityStartDate = DateUtil.beginOfDay(DateUtil.date(activity.getStartTime()));
DateTime activityEndDate = DateUtil.endOfDay(DateUtil.date(activity.getEndTime()));
DateTime todayStartDate = DateUtil.beginOfDay(new Date());
DateTime queryStartDate = todayStartDate;
if ("oneMonth".equals(mode)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offsetMonth(todayStartDate, -1));
} else if ("halfYear".equals(mode)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offsetMonth(todayStartDate, -6));
} else if ("oneYear".equals(mode)) {
queryStartDate = DateUtil.beginOfDay(DateUtil.offset(todayStartDate, DateField.YEAR, -1));
} else if ("activity".equals(mode) || "all".equals(mode)) {
queryStartDate = activityStartDate;
}
// PC端所有时间范围都不得超出活动有效期,查询结束时间取今天和活动结束时间中的较早值。
if (queryStartDate.isBefore(activityStartDate)) {
queryStartDate = activityStartDate;
}
DateTime queryEndDate = DateUtil.endOfDay(new Date());
if (queryEndDate.isAfter(activityEndDate)) {
queryEndDate = activityEndDate;
}
String dateSql = "applyDate >= '" + DateUtil.format(queryStartDate, "yyyy-MM-dd HH:mm:ss")
+ "' AND applyDate <= '" + DateUtil.format(queryEndDate, "yyyy-MM-dd HH:mm:ss") + "'";
sql.setVar("dateSql", new Static(dateSql));
if (Strings.isNotBlank(unitId)) {
cnd.and("u.unitId", "=", unitId);
}
@@ -109,10 +109,11 @@ layout("/layouts/platform.html"){
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="排行榜">
<el-radio-group v-model="pageForm.mode" size="small" @change="doSearch">
<el-radio-button label="today">今日排行榜</el-radio-button>
<el-radio-button label="all">总排行榜</el-radio-button>
<el-radio-button v-for="item in rankingTimeOptions"
:key="item.value"
:label="item.value">{{item.name}}</el-radio-button>
</el-radio-group>
<el-button @click="exportExcel" class="ml10" size="small" type="primary">导出{{pageForm.mode == 'today' ? '今日排行榜' : '总排行榜'}}</el-button>
<el-button @click="exportExcel" class="ml10" size="small" type="primary">导出{{rankingTimeRangeName}}</el-button>
<!-- 独立导出查询尚未修复,暂时隐藏入口,避免用户导出只有表头的空文件。 -->
<!-- <el-button @click="exportExcel2" class="ml10" size="small" type="primary">导出参与人员总步数</el-button> -->
</table-tool>
@@ -162,6 +163,13 @@ layout("/layouts/platform.html"){
unionOptions: [],
unitOptions: [],
activityOptions: [],
rankingTimeOptions: [
{name: '今日排行榜', value: 'today'},
{name: '近1个月', value: 'oneMonth'},
{name: '近半年', value: 'halfYear'},
{name: '近1年', value: 'oneYear'},
{name: '活动开始至今', value: 'activity'}
],
tableColumns: [
{label: '姓名', prop: 'username'},
{label: '工号', prop: 'loginname'},
@@ -174,6 +182,12 @@ layout("/layouts/platform.html"){
],
}
},
computed: {
rankingTimeRangeName() {
const currentOption = this.rankingTimeOptions.find((item) => item.value === this.pageForm.mode)
return currentOption ? currentOption.name : '今日排行榜'
}
},
methods: {
exportExcel(){
const {searchName,searchKeyword,activityId,unionId,unitId,mode,sex,ageRange} = this.pageForm