场地预约整改

This commit is contained in:
=
2026-06-17 14:13:23 +08:00
parent 33859d3be0
commit a5896d3629
15 changed files with 174 additions and 63 deletions
@@ -3,6 +3,7 @@ package com.budwk.app.sys.services.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.budwk.app.sys.services.SysHomeNewsService;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
@@ -23,12 +24,11 @@ public class SysHomeNewsServiceImpl implements SysHomeNewsService {
JSONObject root = new JSONObject();
List<JSONObject> noticeList = new ArrayList<>();
Document doc = Jsoup.connect(UNION_HOME_URL)
// 学校官网会过滤部分非浏览器请求,这里补充常规浏览器请求头提高抓取稳定性。
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36")
.referrer("https://www.jsahvc.edu.cn/")
.timeout(10000)
.get();
Document doc = fetchUnionHomeDocument();
if (doc == null) {
root.set("grassroots", getFallbackNoticeList());
return root;
}
Elements noticeItems = getNoticeItems(doc);
for (Element item : noticeItems) {
@@ -48,10 +48,72 @@ public class SysHomeNewsServiceImpl implements SysHomeNewsService {
noticeList.add(node);
}
if (noticeList.isEmpty()) {
noticeList = getFallbackNoticeList();
}
root.set("grassroots", noticeList);
return root;
}
/**
* 按真实浏览器请求头抓取工会首页;官网防护返回 412 时不抛错,交给调用方使用兜底数据。
*
* @return 可解析的工会首页文档,抓取失败或被防护拦截时返回 null
*/
private Document fetchUnionHomeDocument() throws IOException {
Connection.Response response = createUnionHomeConnection()
.execute();
if (response.statusCode() == 200) {
return response.parse();
}
response = createUnionHomeConnection()
.header("Sec-Fetch-Dest", "document")
.header("Sec-Fetch-Mode", "navigate")
.header("Sec-Fetch-Site", "same-origin")
.header("Sec-Fetch-User", "?1")
.execute();
if (response.statusCode() == 200) {
return response.parse();
}
return null;
}
/**
* 统一组装学校官网请求参数,避免后续调整请求头时遗漏某一次重试。
*
* @return Jsoup 请求连接
*/
private Connection createUnionHomeConnection() {
return Jsoup.connect(UNION_HOME_URL)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36")
.referrer("https://www.jsahvc.edu.cn/")
.timeout(10000)
.followRedirects(true)
.ignoreHttpErrors(true)
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
.header("Cache-Control", "no-cache")
.header("Connection", "keep-alive")
.header("Pragma", "no-cache")
.header("Upgrade-Insecure-Requests", "1");
}
/**
* 官网防护拦截或列表结构变化时,返回可点击入口,避免首页通知公告区域空白。
*
* @return 兜底通知公告列表
*/
private List<JSONObject> getFallbackNoticeList() {
List<JSONObject> fallbackNoticeList = new ArrayList<>();
JSONObject node = new JSONObject();
node.set("title", "江苏农牧科技职业学院工会通知公告");
node.set("date", "");
node.set("url", UNION_HOME_URL);
fallbackNoticeList.add(node);
return fallbackNoticeList;
}
/**
* 优先按栏目标题查找通知公告列表,找不到时再使用学校官网历史模板中的栏目位兜底。
*
@@ -69,13 +69,13 @@ public class FitnessWalkLotteryJob implements Job {
COALESCE(SUM(sub.step), 0) AS total_steps,
u.loginname,
u.username,
u.unionid,
u.unionname,
u.unitid,
u.unitname,
u.unionId AS unionid,
u.unionName AS unionname,
u.unitId AS unitid,
u.unitName AS unitname,
over3k.standardsDays
FROM
`user` u
vw_user u
LEFT JOIN (
SELECT
userId,
@@ -111,8 +111,10 @@ public class FitnessWalkLotteryJob implements Job {
u.id,
u.username,
u.loginname,
u.unionname,
u.unitname
u.unionId,
u.unionName,
u.unitId,
u.unitName
HAVING
$stepHavingSql
""");
@@ -122,7 +124,7 @@ public class FitnessWalkLotteryJob implements Job {
} else {
sql.setVar("stepHavingSql", new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(lotteryQualificationStep)));
}
sql.setVar("whereSql", new Static(" where u.loginname not in (select loginName from fitness_walk_award_user where activityId = " + activityId + " ) "));
sql.setVar("whereSql", new Static(" where u.loginname not in (select loginName from fitness_walk_award_user where activityId = '" + activityId + "' ) "));
sql.setParam("activityId", activityId);
sql.setParam("step", lotteryQualificationStep);
sql.setParam("startDate", startDate);
@@ -134,13 +136,13 @@ public class FitnessWalkLotteryJob implements Job {
jws.userId AS id,
u.username,
u.loginname,
u.unionid,
u.unionname,
u.unitid,
u.unitname
u.unionId AS unionid,
u.unionName AS unionname,
u.unitId AS unitid,
u.unitName AS unitname
FROM
fitness_walk_step jws
LEFT JOIN `user` u ON u.id = jws.userId
LEFT JOIN vw_user u ON u.id = jws.userId
WHERE
jws.activityId = @activityId
AND jws.step >= @step
@@ -84,9 +84,9 @@ public class FitnessWalkActivityManageController {
StringBuilder sql = new StringBuilder("db.collection('activity')");
if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) {
sql.append("where(");
sql.append(".where(");
sql.append("_.or([");
sql.append("{name:{$regex:'").append(searchKeyword).append("',$options:'i'}}");
sql.append("{name:{$regex:'").append(searchKeyword).append("',$options:'i'}},");
sql.append("{tag:{$regex:'").append(searchKeyword).append("',$options:'i'}}");
sql.append("])");
sql.append(")");
@@ -235,10 +235,16 @@ public class FitnessWalkStepManageController {
NutMap resultMap = NutMap.NEW();
FitnessWalkActivity activity = fitnessWalkCommonService.getActivity(activityId);
if (activity == null) {
return Result.error("活动不存在");
}
//计步的抽奖模式 everyday custom
String lotteryMode = activity.getLotteryMode();
if ("everyday".equals(lotteryMode)) {
FitnessWalkActivity.DayLotteryRule dayLotteryRule = activity.getDayLotteryRule();
if (dayLotteryRule == null || dayLotteryRule.getLotteryQualificationStep() == null || dayLotteryRule.getLotteryQualificationStep() <= 0) {
return Result.success(resultMap);
}
//每日抽奖资格步数
Integer lotteryQualificationStep = dayLotteryRule.getLotteryQualificationStep();
@@ -249,7 +255,7 @@ public class FitnessWalkStepManageController {
.and("DATE( applyDate )", "=", DateUtil.today()).and("activityId", "=", activityId)
.and("step", ">", lotteryQualificationStep));
Integer thisDayStep = userWalkStep.getStep();
Integer thisDayStep = userWalkStep == null ? 0 : userWalkStep.getStep();
BigDecimal lotteryQualificationStepBig = new BigDecimal(lotteryQualificationStep);
BigDecimal thisDayStepBig = new BigDecimal(thisDayStep);
@@ -174,7 +174,7 @@ public class FitnessWalkStepRankingController {
activityId,
applyDate
) sub
left join `user` u ON u.id = sub.userId
left join vw_user u ON u.id = sub.userId
GROUP BY
userId
ORDER BY
@@ -208,7 +208,7 @@ public class FitnessWalkStepRankingController {
activityId,
applyDate
) sub
left join `user` u ON u.id = sub.userId
left join vw_user u ON u.id = sub.userId
GROUP BY
userId
ORDER BY
@@ -241,11 +241,11 @@ public class FitnessWalkStepRankingController {
COALESCE(SUM(fws.step), 0) AS total_steps,
u.username,
u.loginname,
u.unionname,
u.unitname
u.unionName AS unionname,
u.unitName AS unitname
FROM
fitness_walk_step fws
LEFT JOIN `user` u ON u.id = fws.userId
LEFT JOIN vw_user u ON u.id = fws.userId
$condition
""");
@@ -69,14 +69,14 @@ public class FitnessWalkStepStatisticsController {
SELECT
u.loginname,
u.username,
u.unionname,
u.unitname,
u.unionName AS unionname,
u.unitName AS unitname,
al.applyDate,
al.step,
date_format(al.applyDate,'%Y-%m-%d') as prizeData
FROM
`fitness_walk_step` al
LEFT JOIN `user` u ON u.id = al.userId
LEFT JOIN vw_user u ON u.id = al.userId
$condition
""";
}
@@ -104,10 +104,10 @@ public class FitnessWalkStepStatisticsController {
}
cnd.andEX("YEAR(al.applyDate)", "=", year);
cnd.andEX("al.activityId", "=", activityId);
cnd.andEX("u.unionid", "=", unionId);
cnd.andEX("u.unionId", "=", unionId);
cnd.andEX("u.unitId", "=", unitId);
cnd.desc("al.applyDate");
cnd.desc("u.unioncode");
cnd.desc("u.unionCode");
cnd.groupBy("al.applyDate", "al.userId");
sql.setCondition(cnd);
@@ -134,10 +134,10 @@ public class FitnessWalkStepStatisticsController {
cnd.and("date_format(al.applyDate,'%Y-%m-%d')", "<=", activityDate[1]);
}
cnd.andEX("al.activityId", "=", activityId);
cnd.andEX("u.unionid", "=", unionId);
cnd.andEX("u.unionId", "=", unionId);
cnd.andEX("u.unitId", "=", unitId);
cnd.desc("al.applyDate");
cnd.desc("u.unioncode");
cnd.desc("u.unionCode");
sql.setCondition(cnd);
List<NutMap> exportList = baseService.listMap(sql);
@@ -106,6 +106,10 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
try {
JSONObject jsonObject = weAppCloudUtil.request(WeAppCloudUtil.CRUD.QUERY, sql.toString());
activity = jsonObject.getJSONArray("data").stream().map(v -> JSON.parseObject((String) v, FitnessWalkActivity.class)).findFirst().orElse(null);
// 活动已删除或传入空 id 时直接返回空,避免后续读取图片字段时空指针。
if (activity == null) {
return null;
}
if (Lang.isNotEmpty(activity.getRandomPics())) {
List<String> urlStr = new ArrayList<>();
for (String url : activity.getRandomPics()) {
@@ -131,6 +135,9 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
}
}
if (activity == null) {
return null;
}
if (AuthUtil.hasRoleOr("BRANCH_UNION_CHAIRMAN", "BRANCH_UNION_OPERATOR", "BRANCH_UNION_ADMIN") && !AuthUtil.hasRoleOr("SYSADMIN")) {
return SecurityUtil.getUnionId().equals(activity.getUnionId()) ? activity : null;
}
@@ -550,11 +557,11 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
COALESCE(SUM(sub.step), 0) AS total_steps,
u.username,
u.loginname,
u.unionname,
u.unitname,
u.unionName AS unionname,
u.unitName AS unitname,
over3k.standardsDays
FROM
`user` u
vw_user u
LEFT JOIN (
SELECT
userId,
@@ -608,7 +615,7 @@ public class FitnessWalkCommonServiceImpl extends BaseServiceImpl<FitnessWalkAwa
cnd.and(searchName, "LIKE", "%" + searchKeyword + "%");
}
// cnd.and("u.id","in",Sqls.create("select userId from activity_user_scope where groupId = @groupId").setParam("groupId",activity.getGroupId()));
cnd.groupBy("u.id","u.username","u.loginname","u.unionname","u.unitname","over3k.standardsDays");
cnd.groupBy("u.id","u.username","u.loginname","u.unionName","u.unitName","over3k.standardsDays");
cnd.desc("total_steps");
cnd.having(Cnd.NEW().and("COALESCE(SUM(sub.step), 0)",">",0));
sql.setCondition(cnd);
@@ -49,6 +49,8 @@ public class FitnessWalkStepRaffleServiceImpl extends BaseServiceImpl<FitnessWal
Integer lotteryQualificationDays = activity.getLotteryQualificationDays();
Integer lotteryQualificationSteps = activity.getLotteryQualificationSteps();
// 兼容历史活动未配置抽奖资格步数的情况,避免生成 >= null 的 SQL。
Integer effectiveLotteryQualificationSteps = lotteryQualificationSteps == null ? 0 : lotteryQualificationSteps;
Date startDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getStartTime()), "yyyy-MM-dd"), "yyyy-MM-dd");
Date endDate = DateUtil.parse(DateUtil.format(DateUtil.date(activity.getEndTime()), "yyyy-MM-dd"), "yyyy-MM-dd");
@@ -59,13 +61,13 @@ public class FitnessWalkStepRaffleServiceImpl extends BaseServiceImpl<FitnessWal
COALESCE(SUM(sub.step), 0) AS total_steps,
u.loginname,
u.username,
u.unionid,
u.unionname,
u.unitid,
u.unitname,
u.unionId AS unionid,
u.unionName AS unionname,
u.unitId AS unitid,
u.unitName AS unitname,
over3k.standardsDays
FROM
`user` u
vw_user u
LEFT JOIN (
SELECT
userId,
@@ -99,16 +101,18 @@ public class FitnessWalkStepRaffleServiceImpl extends BaseServiceImpl<FitnessWal
$condition
""");
if (lotteryQualificationDays != null) {
sql.setVar("lotteryQualificationDaySql", new Static(" AND step >= '%s' ".formatted(lotteryQualificationSteps)));
cnd.having(cnd.and(new Static(" over3k.standardsDays >= '%s' ".formatted(lotteryQualificationDays))));
sql.setVar("lotteryQualificationDaySql", new Static(" AND step >= '%s' ".formatted(effectiveLotteryQualificationSteps)));
cnd.having(Cnd.NEW().and(new Static(" over3k.standardsDays >= '%s' ".formatted(lotteryQualificationDays))));
// sql.setVar("stepHavingSql", new Static(" over3k.standardsDays >= '%s' ".formatted(lotteryQualificationDays)));
} else {
cnd.having(cnd.and(new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(lotteryQualificationSteps))));
} else if (lotteryQualificationSteps != null) {
cnd.having(Cnd.NEW().and(new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(effectiveLotteryQualificationSteps))));
// sql.setVar("stepHavingSql", new Static(" COALESCE(SUM(sub.step), 0) >= '%s' ".formatted(lotteryQualificationSteps)));
} else {
cnd.having(Cnd.NEW().and(new Static(" COALESCE(SUM(sub.step), 0) > 0 ")));
}
sql.setParam("activityId", activityId);
sql.setParam("step", lotteryQualificationSteps);
sql.setParam("step", effectiveLotteryQualificationSteps);
sql.setParam("startDate", startDate);
sql.setParam("endDate", endDate);
@@ -126,7 +130,7 @@ public class FitnessWalkStepRaffleServiceImpl extends BaseServiceImpl<FitnessWal
cnd.and(seg);
}
// cnd.and("u.id","in",Sqls.create("select userId from activity_user_scope where groupId = @groupId").setParam("groupId",activity.getGroupId()));
cnd.groupBy("u.id", "u.username", "u.loginname", "u.unionname", "u.unitname");
cnd.groupBy("u.id", "u.username", "u.loginname", "u.unionId", "u.unionName", "u.unitId", "u.unitName");
cnd.desc("total_steps");
sql.setCondition(cnd);
return sql;
@@ -25,11 +25,11 @@ import java.util.*;
*/
@IocBean
public class WeAppCloudUtil {
public static String ENV = "cloud1-1gxxg6xx50b1860e";
public static String ENV = "cloud1-d8gmetslg087dd762";
private static final String APPID = "wxf750f43635f770e0";
private static final String APPID = "wx34ee585f13eebc04";
private static final String APP_SECRET = "a54517e19ab700f745f20f27312ab8b2";
private static final String APP_SECRET = "2e467f13e8d25a8b3f45a8d08bf286b5";
@Inject
public RedisService redisService;
@@ -99,7 +99,7 @@
src="https://webapi.amap.com/maps?v=2.0&key=b4fa2e2bc10a725ab007b98a3aa447cc&plugin=AMap.PolyEditor,AMap.Geolocation"
></script>-->
<script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script>
<script src="https://map.qq.com/api/gljs?v=2.exp&key=NYNBZ-K62KI-DQJGU-U4NJ5-CSME7-ULFMU&libraries=tools"></script>
<script nonce="${cspNonce!}">
// 在加载 lodash 后、使用前插入
@@ -130,7 +130,8 @@ layout("/layouts/v4/baseLayout.html"){
<work-template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
<jcdt :list="websiteNews.grassroots"></jcdt>
<!-- 官网通知公告抓取会被学校官网防护拦截,先屏蔽展示,保留代码便于后续恢复。 -->
<!-- <jcdt :list="websiteNews.grassroots"></jcdt>-->
</div>
</div>
@@ -163,7 +164,8 @@ layout("/layouts/v4/baseLayout.html"){
'stats': stats,
},
mounted() {
this.getWebSiteNews()
// 官网通知公告抓取会被学校官网防护拦截,先屏蔽请求,保留方法便于后续恢复。
// this.getWebSiteNews()
},
methods: {
getWebSiteNews(){
@@ -20,6 +20,10 @@ const jcdt = {
' </div>',
' </div>',
' </div>',
' <div v-if="!list || list.length === 0" class="jcdt-empty" @click="openUnionHome">',
' <i class="fa fa-bullhorn"></i>',
' <span>江苏农牧科技职业学院工会通知公告</span>',
' </div>',
' </div>',
' </div>',
'</div>'
@@ -39,6 +43,9 @@ const jcdt = {
return
}
window.open(item.url)
},
openUnionHome() {
window.open("https://www.jsahvc.edu.cn/gh/main.htm")
}
},
style: [
@@ -178,6 +185,26 @@ const jcdt = {
'',
'/deep/ .jcdt-item i {',
' color: #007aff;',
'}',
'',
'/deep/ .jcdt-empty {',
' display: flex;',
' align-items: center;',
' justify-content: center;',
' gap: 8px;',
' min-height: 96px;',
' border-radius: 12px;',
' background: #ffffff;',
' box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);',
' color: #19324d;',
' font-size: 16px;',
' font-weight: 600;',
' cursor: pointer;',
'}',
'',
'/deep/ .jcdt-empty i {',
' color: #007aff;',
' font-size: 22px;',
'}'
].join('')
};
@@ -1394,9 +1394,9 @@ layout("/layouts/platform.html"){
const activityList = clone(this.historicalActList)
const data = activityList.find(v => v._id === this.historicalAct)
this.getFile(data.pic)
data.bmsj = [$moment(data.apply_start_time).format('YYYY-MM-DD HH:mm:ss'), $moment(data.apply_end_time).format('YYYY-MM-DD HH:mm:ss')]
data.hdsj = [$moment(data.start_time).format('YYYY-MM-DD HH:mm:ss'), $moment(data.end_time).format('YYYY-MM-DD HH:mm:ss')]
data.drawTime = $moment(data.drawTime).format('YYYY-MM-DD HH:mm:ss')
data.bmsj = [moment(data.apply_start_time).format('YYYY-MM-DD HH:mm:ss'), moment(data.apply_end_time).format('YYYY-MM-DD HH:mm:ss')]
data.hdsj = [moment(data.start_time).format('YYYY-MM-DD HH:mm:ss'), moment(data.end_time).format('YYYY-MM-DD HH:mm:ss')]
data.drawTime = moment(data.drawTime).format('YYYY-MM-DD HH:mm:ss')
data.pts.map(v => {
v.lng = v.location.coordinates[0]
@@ -238,7 +238,7 @@ layout("/layouts/platform.html"){
}
},
pageForm: {
year: $moment().format('YYYY'),
year: moment().format('YYYY'),
unionId:'',
unitId:''
},
@@ -147,7 +147,7 @@ layout("/layouts/platform.html"){
if (!this.activityInfo.startTime || !this.activityInfo.endTime) {
return false
}
return time < $moment(this.activityInfo.startTime) || time > $moment(this.activityInfo.endTime)
return time < moment(this.activityInfo.startTime) || time > moment(this.activityInfo.endTime)
}
},
activityInfo:{},
@@ -181,6 +181,7 @@ layout("/layouts/platform.html"){
this.activityOptions = res.data
if (this.activityOptions && this.activityOptions.length > 0) {
this.pageForm.activityId = this.activityOptions[0].value
this.getActivityById()
this.doSearch()
} else {
this.tableData = []
@@ -188,7 +189,6 @@ layout("/layouts/platform.html"){
})
},
pageData() {
sublime.showLoadingbar();
this.tableLoading = true
let pageForm = clone(this.pageForm)
if (pageForm.activityDate && pageForm.activityDate.length > 0) {
@@ -202,12 +202,14 @@ layout("/layouts/platform.html"){
this.$message.error(data.msg);
}
}).finally(() => {
sublime.closeLoadingbar();
this.tableLoading = false
});
},
getActivityById(){
if (!this.pageForm.activityId) {
return
}
this.$axios.post('/platform/fitnessWalk/activityManage/findOne', {id:this.pageForm.activityId}).then((resp) => {
if (resp.code === 0){
this.activityInfo = resp.data
@@ -222,7 +224,6 @@ layout("/layouts/platform.html"){
}).then((res) => {
this.unitOptions = res
this.getCascadersActivity()
this.getActivityById();
})
}
})