From 4288a97beecefaf77a3a9c2bc898730b567a6cc8 Mon Sep 17 00:00:00 2001 From: hongqiwei <1143662660@qq.com> Date: Mon, 14 Sep 2026 17:25:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=BA=E5=9C=B0=E9=A2=84=E7=BA=A6,=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=BC=80=E5=85=B3=E6=8C=89=E9=92=AE=E6=8A=A5=E9=94=99?= =?UTF-8?q?bug=20=E8=AF=84=E4=BC=98=E8=AF=84=E5=85=88=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=B8=AA=E4=BA=BA/=E9=9B=86?= =?UTF-8?q?=E4=BD=93=E7=AD=9B=E9=80=89=20=E6=85=B0=E9=97=AE=E3=80=81?= =?UTF-8?q?=E7=89=B9=E5=9B=B0=E6=97=B6=E9=97=B4=E9=85=8D=E7=BD=AE=E5=86=99?= =?UTF-8?q?=E5=88=B0=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/sys/controller/SysHomeController.java | 44 +------ .../app/sys/services/SysHomeNewsService.java | 16 +++ .../services/impl/SysHomeNewsServiceImpl.java | 122 ++++++++++++++++++ .../EvaluateActivityController.java | 46 +++---- .../controller/EvaluateApplyController.java | 38 ++---- .../controller/EvaluateCommonController.java | 18 +++ .../controller/EvaluateMineController.java | 55 ++------ .../controller/EvaluateSummaryController.java | 7 +- .../service/EvaluateActivityService.java | 36 ++++++ .../evaluation/service/EvaluateService.java | 8 ++ .../impl/EvaluateActivityServiceImpl.java | 83 ++++++++++++ .../service/impl/EvaluateServiceImpl.java | 51 ++++++++ .../evaluation/vo/EvaluatePageForm.java | 4 + .../controller/SiteCugManageController.java | 23 ++++ .../siteCug/service/SiteCugInfoService.java | 7 + .../service/impl/SiteCugInfoServiceImpl.java | 26 ++++ .../views/layouts/v4/home/index.html | 5 +- .../resources/views/layouts/v4/home/jcdt.js | 10 +- .../evaluation/activity/index.html | 9 ++ .../dayofficework/evaluation/apply/index.html | 28 +++- .../evaluation/branchUnionApproval/index.html | 48 +++++-- .../dayofficework/evaluation/mine/index.html | 22 +++- .../evaluation/schoolUnionApproval/index.html | 46 ++++++- .../evaluation/summary/index.html | 46 ++++++- .../dayofficework/siteCug/manage/index.html | 28 +++- 25 files changed, 648 insertions(+), 178 deletions(-) create mode 100644 src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java create mode 100644 src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java diff --git a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java index cb32dd5..65800bb 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java @@ -12,25 +12,20 @@ import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.models.Sys_home_template; import com.budwk.app.sys.models.Sys_menu; import com.budwk.app.sys.services.SysMenuService; +import com.budwk.app.sys.services.SysHomeNewsService; import com.budwk.app.sys.services.SysUserService; import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService; import io.swagger.annotations.ApiOperation; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.FieldFilter; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.dao.util.Daos; -import org.nutz.integration.jedis.RedisService; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.json.Json; import org.nutz.lang.Lang; import org.nutz.lang.Strings; import org.nutz.lang.util.NutMap; @@ -42,9 +37,7 @@ import org.nutz.mvc.annotation.Param; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; -import java.io.IOException; import java.util.*; -import java.util.stream.Collectors; @IocBean @@ -58,7 +51,7 @@ public class SysHomeController { @Inject private SysUserService sysUserService; @Inject - private RedisService redisService; + private SysHomeNewsService sysHomeNewsService; @Inject private ActivityBasicScopeService activityBasicScopeService; @@ -278,38 +271,15 @@ public class SysHomeController { } + /** + * 无需请求参数;返回 Result,data 为四个板块的 label/value 列表。 + * value 中 href 为原文绝对链接,time 为 yyyy-MM-dd 发布日期,text 为完整标题。 + */ @At @SaCheckLogin @ApiOperation("获取新闻") @Ok("json") -// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true) -// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24) public Result getNews() { - try { - String url = "https://xgh.cug.edu.cn/"; - Document document = Jsoup.connect(url).get(); - Elements homeElements = document.select(".gh,.jc,.fc,.jg"); - - List> news = homeElements.stream().map(homeElement -> { - //获取板块名称 - String name = homeElement.selectFirst(".title").text(); - Elements liElements = homeElement.select("li"); - List ele = liElements.stream().map(liElement -> { - NutMap row = NutMap.NEW(); - String href = liElement.selectFirst("a").attr("href"); - String time = liElement.selectFirst("span").text(); - String title = liElement.selectFirst("a").attr("title"); - row.put("href", href); - row.put("time", time); - row.put("text", title); - return row; - }).toList(); - return Map.of("label", name, "value", ele); - }).collect(Collectors.toList()); - redisService.setex("gonghui_news", 60 * 60 * 24, Json.toJson(news)); - return Result.success(news); - } catch (IOException e) { - throw new RuntimeException(e); - } + return Result.success(sysHomeNewsService.getNews()); } } diff --git a/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java b/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java new file mode 100644 index 0000000..46c137d --- /dev/null +++ b/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java @@ -0,0 +1,16 @@ +package com.budwk.app.sys.services; + +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface SysHomeNewsService { + + /** + * 获取工会官网首页四个新闻板块,无需传入参数。 + * 返回列表按新闻中心、图片新闻、建功立业、民主管理排序;label 为板块名称, + * value 为新闻列表,每条包含 href(原文绝对地址)、time(发布日期 yyyy-MM-dd)、text(完整标题)。 + * 官网暂不可用时返回上次成功结果;尚无成功结果时返回四个空板块。 + */ + List getNews(); +} diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java new file mode 100644 index 0000000..bec237b --- /dev/null +++ b/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java @@ -0,0 +1,122 @@ +package com.budwk.app.sys.services.impl; + +import com.budwk.app.sys.services.SysHomeNewsService; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.log.Log; +import org.nutz.log.Logs; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@IocBean +public class SysHomeNewsServiceImpl implements SysHomeNewsService { + private static final Log log = Logs.get(); + private static final String BASE_URL = "https://gh.swufe.edu.cn/"; + private static final List LABELS = List.of("新闻中心", "图片新闻", "建功立业", "民主管理"); + private static final Pattern DATE = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); + private static final int REQUEST_TIMEOUT = 5000; + private static final long CACHE_MILLIS = 30 * 60 * 1000L; + private static final long RETRY_MILLIS = 60 * 1000L; + + // 仅缓存官网读取结果,不写业务库;失败时保留上次完整结果,防止临时网络故障清空首页。 + private List cachedNews = emptySections(); + private long nextRefreshTime; + + /** + * 无入参,返回 label/value 板块列表,新闻字段为 href/time/text,含义见接口说明。 + * 同步刷新避免并发访问重复抓取;成功缓存 30 分钟,失败后至少间隔 1 分钟再尝试。 + */ + @Override + public synchronized List getNews() { + if (System.currentTimeMillis() < nextRefreshTime) { + return cachedNews; + } + try { + cachedNews = fetchNews(); + nextRefreshTime = System.currentTimeMillis() + CACHE_MILLIS; + } catch (IOException | IllegalArgumentException e) { + nextRefreshTime = System.currentTimeMillis() + RETRY_MILLIS; + log.warn("工会官网新闻拉取失败,保留上次成功结果", e); + } + return cachedNews; + } + + /** 按板块标题定位容器,官网存在重复组件 ID,不能直接用 ID 区分建功立业和基层动态。 */ + private List fetchNews() throws IOException { + Document document = loadDocument(BASE_URL); + List sections = new ArrayList<>(); + for (String label : LABELS) { + Element heading = document.select(".in-title > span").stream() + .filter(element -> label.equals(element.text().trim())) + .findFirst().orElse(null); + if (heading == null || heading.parent() == null || heading.parent().parent() == null) { + throw new IOException("工会官网缺少板块:" + label); + } + List rows = new ArrayList<>(); + for (Element anchor : heading.parent().parent().select("li a[href]")) { + String href = anchor.absUrl("href"); + String title = anchor.attr("title").trim(); + if (title.isEmpty()) { + Element titleElement = anchor.clone(); + titleElement.select("span").remove(); + title = titleElement.text().trim(); + } + if (title.isEmpty() || href.isEmpty()) { + throw new IOException("工会官网新闻缺少标题或链接:" + label); + } + String date; + if ("图片新闻".equals(label)) { + // 首页图片轮播不含日期,只读取详情中的“发布日期”,避免误用标题中的年份。 + Document detail = loadDocument(href); + Element published = detail.select("p").stream() + .filter(element -> element.text().trim().startsWith("发布日期")) + .findFirst().orElse(null); + date = published == null ? "" : findDate(published.text()); + } else { + date = findDate(anchor.select("span").text()); + } + if (date.isEmpty()) { + throw new IOException("工会官网新闻缺少发布日期:" + href); + } + rows.add(NutMap.NEW().setv("href", href).setv("time", date).setv("text", title)); + } + if (rows.isEmpty()) { + throw new IOException("工会官网板块无可用新闻:" + label); + } + sections.add(NutMap.NEW().setv("label", label).setv("value", rows)); + } + return sections; + } + + /** 请求固定工会站点的公开页面,限制超时且不跟随重定向,避免官网异常拖住首页请求。 */ + private Document loadDocument(String url) throws IOException { + URI uri = URI.create(url); + if (!"https".equalsIgnoreCase(uri.getScheme()) || !"gh.swufe.edu.cn".equalsIgnoreCase(uri.getHost())) { + throw new IOException("工会官网返回了非本站 HTTPS 链接:" + url); + } + return Jsoup.connect(url).timeout(REQUEST_TIMEOUT).followRedirects(false).get(); + } + + /** 将官网方括号日期或发布日期文字统一为 yyyy-MM-dd;无日期时由调用方按抓取失败处理。 */ + private String findDate(String text) { + Matcher matcher = DATE.matcher(text); + return matcher.find() ? matcher.group() : ""; + } + + /** 首次抓取失败时仍保留四个板块的顺序与名称,不用虚构新闻或日期填充。 */ + private static List emptySections() { + List sections = new ArrayList<>(); + for (String label : LABELS) { + sections.add(NutMap.NEW().setv("label", label).setv("value", List.of())); + } + return sections; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateActivityController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateActivityController.java index deb8a0e..1ff0de4 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateActivityController.java @@ -10,7 +10,7 @@ import cn.hutool.core.lang.tree.TreeUtil; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService; import com.budwk.app.sys.models.Sys_union; import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant; import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity; @@ -21,8 +21,6 @@ import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -46,7 +44,7 @@ public class EvaluateActivityController { private Dao dao; @Inject - private BaseService baseService; + private EvaluateActivityService evaluateActivityService; @At("") @Ok("beetl:/platform/zhgh/dayofficework/evaluation/activity/index.html") @@ -55,27 +53,19 @@ public class EvaluateActivityController { } + /** + * 按组合条件获取活动分页数据。 + * @param pageForm 分页参数,pageNumber 为页码,pageSize 为每页条数 + * @param year 年度,未传时不限制年度 + * @param searchKeyword 活动名称关键字,空值时不限制名称 + * @param honorTypeId 个人或集体荣誉的分类 ID,空值表示全部荣誉类型 + * @return Result,data 为分页对象,其中 list 为活动记录,totalCount 为符合条件的总条数 + */ @At @SaCheckPermission("evaluation.activity") @ApiOperation("获取评优评先活动列表") - public Result pageData(@Valid PageForm pageForm, Integer year, String searchKeyword) { - Sql sql = Sqls.create(""" - SELECT - eva.*, - hb.NAME AS honorName, - bs.name as honorTypeName, - ( SELECT groupName FROM activity_user_scope au WHERE au.groupId = eva.activityGroupId LIMIT 1 ) AS groupName - FROM - `evaluate_activity` eva - LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId - LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.andEX("year", "=", year); - cnd.and(Cnd.likeEX("eva.name", searchKeyword)); - sql.setCondition(cnd); - return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + public Result pageData(@Valid PageForm pageForm, Integer year, String searchKeyword, String honorTypeId) { + return Result.success(evaluateActivityService.queryActivityPage(pageForm, year, searchKeyword, honorTypeId)); } @At @@ -150,12 +140,16 @@ public class EvaluateActivityController { return Result.success(); } + /** + * @param year 活动年度,空值不限制 + * @param honorTypeId 荣誉分类 ID,空值表示全部分类 + * @return Result,data 为事项列表,id 为选项值,name 为选项名称 + */ @At @SaCheckLogin - @ApiOperation("根据年查询荣誉申请事项") - public Result listEvaluateActivityByYear(Integer year) { - List list = dao.query(EvaluateActivity.class, Cnd.NEW().andEX(EvaluateActivity::getYear,"=",year)); - return Result.success(list); + @ApiOperation("根据年度和荣誉类型查询申请事项") + public Result listEvaluateActivityByYear(Integer year, String honorTypeId) { + return Result.success(evaluateActivityService.listActivityOptions(year, honorTypeId)); } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateApplyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateApplyController.java index d94faf9..eba78c4 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateApplyController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateApplyController.java @@ -3,8 +3,7 @@ package com.budwk.app.zhgh.dayofficework.evaluation.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.Dict; import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.param.PageForm; +import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm; import com.budwk.app.base.result.Result; import com.budwk.app.flow.constant.FlowConst; import com.budwk.app.flow.engine.FlowEngine; @@ -21,10 +20,7 @@ import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -59,34 +55,16 @@ public class EvaluateApplyController { public void index() { } + /** + * 按年度和荣誉类型查询可申请活动。 + * @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为分类 ID;年度、分类为空时不限制 + * @return Result,data.list 为记录列表,data.totalCount 为符合条件的总条数 + */ @At @SaCheckPermission("evaluation.apply") @ApiOperation("获取评优评先活动列表") - public Result pageData(@Valid PageForm pageForm, Integer year) { - Sql sql = Sqls.create(""" - SELECT - eva.id, - eva.honorId, - eva.honorTypeId, - eva.name, - eva.startTime, - eva.endTime, - eva.enable, - eva.year, - hb.NAME AS honorName, - bs.name as honorTypeName - FROM - evaluate_activity eva - LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId - LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.and("enable", "=", 1); - cnd.andEX("year", "=", year); - sql.setCondition(cnd); - Pagination pagination = evaluateActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); + public Result pageData(@Valid EvaluatePageForm pageForm) { + return Result.success(evaluateActivityService.listApplyPage(pageForm)); } @At diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateCommonController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateCommonController.java index 021b52a..d63a78e 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateCommonController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateCommonController.java @@ -1,6 +1,8 @@ package com.budwk.app.zhgh.dayofficework.evaluation.controller; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService; import cn.hutool.core.bean.BeanUtil; import com.budwk.app.base.constant.BpmProcessConstant; import com.budwk.app.base.result.Result; @@ -25,6 +27,8 @@ public class EvaluateCommonController { @Inject private EvaluateService evaluateService; @Inject + private EvaluateActivityService evaluateActivityService; + @Inject private BpmService bpmService; @At @@ -34,4 +38,18 @@ public class EvaluateCommonController { EvaluateApply evaluateApply = evaluateService.fetch(id); return Result.success(evaluateApply); } + + /** + * 为评优评先各角色提供荣誉类型下拉选项,无需活动管理权限。 + * @return Result,data 为分类列表,id 为分类 ID,name 为个人或集体荣誉名称 + */ + @At + @SaCheckPermission(value = {"evaluation.activity", "evaluation.apply", "evaluation.mine", + "evaluation.unitApproval", "evaluation.branchUnionApproval", "evaluation.partyOrganizationApproval", + "evaluation.schoolUnionApproval", "evaluation.summary"}, mode = SaMode.OR) + @ApiOperation("查询评优评先荣誉类型选项") + public Result honorTypes() { + return Result.success(evaluateActivityService.listHonorTypes()); + } + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateMineController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateMineController.java index 2550ee8..48b9cb4 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateMineController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateMineController.java @@ -2,18 +2,14 @@ package com.budwk.app.zhgh.dayofficework.evaluation.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.page.Pagination; -import com.budwk.app.base.param.PageForm; +import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm; import com.budwk.app.base.result.Result; import com.budwk.app.bpm.service.BpmService; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.nutz.dao.Cnd; import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.mvc.annotation.At; @@ -40,50 +36,15 @@ public class EvaluateMineController { public void index() { } + /** + * 按年度和荣誉类型查询当前用户的申请记录。 + * @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为分类 ID;年度、分类为空时不限制 + * @return Result,data.list 为记录列表,data.totalCount 为符合条件的总条数 + */ @At @SaCheckPermission("evaluation.mine") - public Result pageData(@Valid PageForm pageForm, Integer year) { - - Sql sql = Sqls.create(""" - SELECT - info.*, - ea.name AS evaluateName, - hb.name AS honorName, - bs.name as honorTypeName, - ins.id AS instanceId, - ins.businessNo, - ins.state instanceState, - ins.variable instanceVariable, - ins.processDefineId instanceProcessDefineId, - t.id taskId, - t.taskName AS taskKey, - t.displayName taskName, - t.taskType, - t.performType taskPerformType, - t.taskState, - t.finishTime, - t.taskParentId, - t.variable taskVariable, - IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, - (SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask' AND taskState IN (10, 20)) AS startTaskId - FROM - evaluate_apply info - LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId - LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId - LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId - LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id - LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id - AND t.taskState = 10 - LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.andEX("YEAR(info.year)", "=", year); - cnd.and("info.loginName", "=", SecurityUtil.getUserLoginname()); - cnd.desc("info.createdAt"); - sql.setCondition(cnd); - Pagination pagination = evaluateService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); + public Result pageData(@Valid EvaluatePageForm pageForm) { + return Result.success(evaluateService.listMinePage(pageForm)); } @At diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateSummaryController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateSummaryController.java index e6ea57c..fce42ac 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateSummaryController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/controller/EvaluateSummaryController.java @@ -66,7 +66,8 @@ public class EvaluateSummaryController { @SaCheckPermission("evaluation.summary") @ApiOperation("导出评优评先活动列表") public void exportExcel(@Valid EvaluatePageForm pageForm, HttpServletResponse response) { - EvaluateActivity activity = evaluateService.dao().fetch(EvaluateActivity.class, pageForm.getEvaluateId()); + EvaluateActivity activity = org.nutz.lang.Strings.isBlank(pageForm.getEvaluateId()) ? null + : evaluateService.dao().fetch(EvaluateActivity.class, pageForm.getEvaluateId()); Sql sql = evaluateService.getSummarySql(pageForm); List list = baseService.listMap(sql); for (int i = 0; i < list.size(); i++) { @@ -88,7 +89,9 @@ public class EvaluateSummaryController { ExportParams exportParams = new ExportParams(); exportParams.setType(ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list); - CommonDownloadUtil.download(activity.getName() + "人员列表.xlsx", workbook, response); + // 全部事项或当前分类下无事项时使用通用名称,避免空事项导致导出失败。 + String fileName = activity == null ? "评优评先人员列表.xlsx" : activity.getName() + "人员列表.xlsx"; + CommonDownloadUtil.download(fileName, workbook, response); } catch (Exception ignored) { } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateActivityService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateActivityService.java index d7142ec..d074508 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateActivityService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateActivityService.java @@ -1,7 +1,43 @@ package com.budwk.app.zhgh.dayofficework.evaluation.service; import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm; +import com.budwk.app.zhgh.dayofficework.honor.models.HonorBasicSettings; +import java.util.List; import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity; public interface EvaluateActivityService extends BaseService { + /** + * 按年度、名称和荣誉类型组合查询活动。 + * @param pageForm 分页参数,包含页码 pageNumber 和每页条数 pageSize + * @param year 年度,空值时不限制 + * @param searchKeyword 活动名称关键字,空值时不限制 + * @param honorTypeId 荣誉分类 ID,空值表示全部个人和集体荣誉 + * @return 分页对象,list 为包含荣誉名称、类型名称及人员范围名称的活动记录,totalCount 为总条数 + */ + Pagination queryActivityPage(PageForm pageForm, Integer year, String searchKeyword, String honorTypeId); + + /** + * 查询已启用的可申请活动。 + * @param pageForm pageNumber/pageSize 为页码和每页条数,year 为年度,honorTypeId 为分类 ID;空筛选不限制 + * @return 分页对象,list 为活动及荣誉名称,totalCount 为总条数 + */ + Pagination listApplyPage(EvaluatePageForm pageForm); + + /** + * 查询评优评先一级荣誉分类,供各列表页面选择个人或集体荣誉。 + * @return 分类列表,id 为查询使用的分类 ID,name 为显示名称;未配置根分类时返回空列表 + */ + List listHonorTypes(); + + /** + * 按查询条件提供事项下拉选项。 + * @param year 活动年度,空值不限制 + * @param honorTypeId 荣誉分类 ID,空值表示全部 + * @return 活动列表,id 为事项值,name 为事项名称 + */ + List listActivityOptions(Integer year, String honorTypeId); + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateService.java index 4cb7244..f482d8d 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/EvaluateService.java @@ -29,4 +29,12 @@ public interface EvaluateService extends BaseService { * @return 流程决策节点使用的路线参数值 */ String getApprovalRoute(String unionId); + + /** + * 查询当前登录用户的申请记录,保留原有流程信息和排序。 + * @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为荣誉分类 ID;空筛选不限制 + * @return 分页对象,list 为申请及流程信息,totalCount 为总条数 + */ + Pagination listMinePage(EvaluatePageForm pageForm); + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateActivityServiceImpl.java index ea61389..449c17f 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateActivityServiceImpl.java @@ -1,9 +1,18 @@ package com.budwk.app.zhgh.dayofficework.evaluation.service.impl; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm; +import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant; +import com.budwk.app.zhgh.dayofficework.honor.models.HonorBasicSettings; +import java.util.List; import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity; import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService; import org.nutz.dao.Dao; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.IocBean; @IocBean(args = {"refer:dao"}) @@ -12,4 +21,78 @@ public class EvaluateActivityServiceImpl extends BaseServiceImpl listActivityOptions(Integer year, String honorTypeId) { + return query(Cnd.NEW().andEX("year", "=", year).andEX("honorTypeId", "=", honorTypeId)); + } + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateServiceImpl.java index 7d7b6ef..60e801e 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/service/impl/EvaluateServiceImpl.java @@ -65,6 +65,8 @@ public class EvaluateServiceImpl extends BaseServiceImpl implemen Cnd cnd = Cnd.NEW(); cnd.andEX("YEAR(info.applyDateTime)", "=", pageForm.getYear()); cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId()); + // 分类条件同时用于审核列表、统计列表及统计导出,空值时不限制。 + cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId()); cnd.and("ins.state", "=", ProcessTaskStateEnum.FINISHED.getCode()); cnd.andEX("info.unitId", "=", pageForm.getUnitId()); cnd.andEX("info.unionId", "=", pageForm.getUnionId()); @@ -126,6 +128,8 @@ public class EvaluateServiceImpl extends BaseServiceImpl implemen cnd.and("t.taskName", "=", taskKey); cnd.and("ta.actorId", "=", SecurityUtil.getUserId()); cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId()); + // 分类条件同时用于审核列表、统计列表及统计导出,空值时不限制。 + cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId()); cnd.andEX("info.unionId", "=", pageForm.getUnionId()); cnd.andEX("info.unitId", "=", pageForm.getUnitId()); @@ -171,4 +175,51 @@ public class EvaluateServiceImpl extends BaseServiceImpl implemen ? EvaluateConstant.UNIT_APPROVAL_ROUTE : EvaluateConstant.BRANCH_UNION_APPROVAL_ROUTE; } + + /** {@inheritDoc} */ + @Override + public Pagination listMinePage(EvaluatePageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + info.*, + ea.name AS evaluateName, + hb.name AS honorName, + bs.name as honorTypeName, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + ins.processDefineId instanceProcessDefineId, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, + (SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask' AND taskState IN (10, 20)) AS startTaskId + FROM + evaluate_apply info + LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId + LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId + LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id + AND t.taskState = 10 + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(info.year)", "=", pageForm.getYear()); + cnd.and("info.loginName", "=", SecurityUtil.getUserLoginname()); + cnd.desc("info.createdAt"); + // 空分类表示全部;选中分类时按当前记录的荣誉类型精确过滤。 + cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId()); + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/vo/EvaluatePageForm.java b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/vo/EvaluatePageForm.java index 94ad602..f6f070d 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/vo/EvaluatePageForm.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/evaluation/vo/EvaluatePageForm.java @@ -11,6 +11,10 @@ import lombok.EqualsAndHashCode; @Data public class EvaluatePageForm extends PageForm { + /** 个人或集体荣誉的分类 ID,空值表示全部荣誉类型。 */ + @ApiModelProperty("荣誉类型ID,空值表示全部") + private String honorTypeId; + @ApiModelProperty("年度") private Integer year; diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/controller/SiteCugManageController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/controller/SiteCugManageController.java index b90572d..21ad26e 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/controller/SiteCugManageController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/controller/SiteCugManageController.java @@ -15,6 +15,8 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.ioc.aop.Aop; import org.nutz.dao.Dao; import org.nutz.dao.util.cri.SqlExpressionGroup; import org.nutz.ioc.loader.annotation.Inject; @@ -76,11 +78,32 @@ public class SiteCugManageController { return Result.success(pagination); } + /** + * 仅切换场地开关:id 为已有场地 ID,state 为 true(开启)或 false(禁用)。 + * 返回 Result,code=0 表示成功,data 为保存后的 Boolean 状态;参数无效返回错误消息。 + */ + @At + @ApiOperation("切换场地开启状态") + @SaCheckPermission("siteCug.manage") + @Aop(TransAop.READ_COMMITTED) + @SLog(tag = "siteCug.manage", msg = "切换场地开启状态") + public Result updateState(@Param("id") String id, @Param("state") Boolean state) { + if (StrUtil.isBlank(id) || state == null) { + return Result.error("场地ID和开启状态不能为空"); + } + return Result.success(infoService.updateState(id, state)); + } + @At @ApiOperation("submit") + @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("siteCug.manage") @SLog(tag = "siteCug.manage", msg = "submit site") public Object submit(@Param("data") SiteCugInfo info) { + // 完整表单必须通过 data 参数提交;缺失时返回业务提示,避免空指针异常。 + if (info == null) { + return Result.error("场地信息不能为空,请通过data参数提交完整表单"); + } List notApplyTimeList = info.getNotApplyTimeList(); if (notApplyTimeList != null) { boolean invalid = notApplyTimeList.stream().anyMatch(item -> diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/SiteCugInfoService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/SiteCugInfoService.java index 1fa2d0b..bf2307b 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/SiteCugInfoService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/SiteCugInfoService.java @@ -4,4 +4,11 @@ import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugInfo; public interface SiteCugInfoService extends BaseService { + /** + * 切换已有场地的开启状态,不改动开放时段及预约限制。 + * @param id 场地业务 ID,不允许为空 + * @param state true 开启,false 禁用,不允许为 null + * @return 保存后的开启状态;场地不存在或已删除时抛出业务异常 + */ + boolean updateState(String id, Boolean state); } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/impl/SiteCugInfoServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/impl/SiteCugInfoServiceImpl.java index 0292fb6..478a131 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/impl/SiteCugInfoServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/siteCug/service/impl/SiteCugInfoServiceImpl.java @@ -1,10 +1,17 @@ package com.budwk.app.zhgh.dayofficework.siteCug.service.impl; import com.budwk.app.base.service.impl.BaseServiceImpl; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugInfo; import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugInfoService; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Dao; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.ioc.aop.Aop; +import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.ioc.loader.annotation.IocBean; @Slf4j @@ -14,4 +21,23 @@ public class SiteCugInfoServiceImpl extends BaseServiceImpl impleme public SiteCugInfoServiceImpl(Dao dao) { super(dao); } + + /** {@inheritDoc} */ + @Override + @Aop(TransAop.READ_COMMITTED) + public boolean updateState(String id, Boolean state) { + if (StrUtil.isBlank(id) || state == null) { + throw new BaseException("场地ID和开启状态不能为空"); + } + SiteCugInfo info = fetch(id); + if (info == null || Boolean.TRUE.equals(info.getDelFlag())) { + throw new BaseException("场地不存在或已删除"); + } + // 只写状态及审计字段,缺少开放时段的历史场地也能关闭,且不会覆盖其他配置。 + update(Chain.make("state", state) + .add("updatedBy", SecurityUtil.getUserId()) + .add("updatedAt", System.currentTimeMillis()), + Cnd.where("id", "=", id)); + return state; + } } diff --git a/src/main/resources/views/layouts/v4/home/index.html b/src/main/resources/views/layouts/v4/home/index.html index a2f9f0f..ae37fc1 100644 --- a/src/main/resources/views/layouts/v4/home/index.html +++ b/src/main/resources/views/layouts/v4/home/index.html @@ -164,11 +164,14 @@ layout("/layouts/v4/baseLayout.html"){ this.getWebSiteNews() }, methods: { + // 无请求参数;data 为四个新闻板块,沿用 label/value 及 href/time/text 展示结构。 getWebSiteNews(){ this.$axios.post('/platform/home/getNews').then(res => { if (res.code === 0) { - this.websiteNews = res.data + this.$set(this, 'websiteNews', res.data) } + }).catch(() => { + this.$message.error('获取工会新闻失败,请稍后重试') }) } } diff --git a/src/main/resources/views/layouts/v4/home/jcdt.js b/src/main/resources/views/layouts/v4/home/jcdt.js index dbeefbc..b6cc642 100644 --- a/src/main/resources/views/layouts/v4/home/jcdt.js +++ b/src/main/resources/views/layouts/v4/home/jcdt.js @@ -26,6 +26,7 @@ const jcdt = { + `, data() { @@ -39,11 +40,10 @@ const jcdt = { }, methods: { onLink(item) { - const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href - window.open(url) - }, - isHttpOrHttps(url) { - return /^(http:\/\/|https:\/\/)/i.test(url) + // service 返回工会官网原文绝对地址,仅允许本站 HTTPS 新闻在新窗口打开。 + if (item.href && /^https:\/\/gh\.swufe\.edu\.cn\//i.test(item.href)) { + window.open(item.href, '_blank', 'noopener') + } } }, style: /*language=CSS*/ ` diff --git a/src/main/resources/views/platform/zhgh/dayofficework/evaluation/activity/index.html b/src/main/resources/views/platform/zhgh/dayofficework/evaluation/activity/index.html index a8b7d94..4bff902 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/evaluation/activity/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/evaluation/activity/index.html @@ -8,6 +8,13 @@ layout("/layouts/platform.html"){ + + + + + + + @@ -299,6 +306,8 @@ layout("/layouts/platform.html"){ } }, created() { + // 默认查询全部荣誉类型,与年度、名称共同参与现有分页查询。 + this.$set(this.pageForm, "honorTypeId", "") this.$set(this.pageForm, "year", new Date().getFullYear().toString()) this.listHonorType() this.getActivityGroup() diff --git a/src/main/resources/views/platform/zhgh/dayofficework/evaluation/apply/index.html b/src/main/resources/views/platform/zhgh/dayofficework/evaluation/apply/index.html index 4af9b82..aadb447 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/evaluation/apply/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/evaluation/apply/index.html @@ -11,6 +11,13 @@ layout("/layouts/platform.html"){ + + + + + + + @@ -46,19 +53,34 @@ layout("/layouts/platform.html"){