From 478b70c2d1d3280cc459b38b224614407d16e733 Mon Sep 17 00:00:00 2001 From: zhouhefeng Date: Tue, 1 Sep 2026 18:00:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E6=94=B9=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=99=BB=E5=BD=95=20=E6=95=B4=E6=94=B9?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=90=E6=A1=88UI=20=E6=95=B4=E6=94=B9?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BD=9C=E5=93=81=E5=BE=81=E9=9B=86UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../satoken/aop/SaCheckLoginInterceptor.java | 4 + .../aop/SaCheckPermissionInterceptor.java | 4 + .../satoken/aop/SaCheckRoleInterceptor.java | 4 + .../satoken/aop/SaTokenAuthIgnoreUtil.java | 60 +++ ...tivityWorksCollectionManageController.java | 19 +- .../ActivityWorksCollectionService.java | 8 + .../ActivityWorksCollectionServiceImpl.java | 132 +++++ .../transact/ProposalSecondedController.java | 5 +- .../ProposalUnderTakeReplyController.java | 2 +- .../proposal/param/ProposalSearchParam.java | 2 +- .../proposal/transact/unitReply/index.html | 21 +- .../activity/workscollection/mine/index.html | 8 +- .../activity/workscollection/mine/info.js | 9 +- .../activity/workscollection/read/index.html | 29 +- .../workscollection/upload/applyForm.js | 20 +- .../democratic/proposal/common/info.css | 27 +- .../zhghh5/democratic/proposal/common/info.js | 69 ++- .../democratic/proposal/common/task-popup.js | 458 +++++++++++++++--- .../proposal/transact/mine/index.html | 184 +++++++ .../proposal/transact/mine/inviteSeconder.js | 103 ++-- .../proposal/transact/seconded/index.html | 2 +- .../proposal/transact/unitReply/index.html | 153 +++++- .../proposal/transact/unitReply/transfer.js | 73 ++- 23 files changed, 1181 insertions(+), 215 deletions(-) create mode 100644 src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaTokenAuthIgnoreUtil.java diff --git a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckLoginInterceptor.java b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckLoginInterceptor.java index 04fd258c..6f9644fb 100644 --- a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckLoginInterceptor.java +++ b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckLoginInterceptor.java @@ -15,6 +15,10 @@ import java.lang.reflect.Method; public class SaCheckLoginInterceptor implements MethodInterceptor { @Override public void filter(InterceptorChain chain) throws Throwable { + if (SaTokenAuthIgnoreUtil.isIgnore()) { + chain.doChain(); + return; + } Method method = chain.getCallingMethod(); SaCheckLogin at = method.getAnnotation(SaCheckLogin.class); SaManager.getStpLogic(at.type()).checkByAnnotation(at); diff --git a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckPermissionInterceptor.java b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckPermissionInterceptor.java index c1004bf1..2eac0990 100644 --- a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckPermissionInterceptor.java +++ b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckPermissionInterceptor.java @@ -15,6 +15,10 @@ import java.lang.reflect.Method; public class SaCheckPermissionInterceptor implements MethodInterceptor { @Override public void filter(InterceptorChain chain) throws Throwable { + if (SaTokenAuthIgnoreUtil.isIgnore()) { + chain.doChain(); + return; + } Method method = chain.getCallingMethod(); SaCheckPermission at = method.getAnnotation(SaCheckPermission.class); SaManager.getStpLogic(at.type()).checkByAnnotation(at); diff --git a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckRoleInterceptor.java b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckRoleInterceptor.java index 7df25c08..c87fd80e 100644 --- a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckRoleInterceptor.java +++ b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaCheckRoleInterceptor.java @@ -15,6 +15,10 @@ import java.lang.reflect.Method; public class SaCheckRoleInterceptor implements MethodInterceptor { @Override public void filter(InterceptorChain chain) throws Throwable { + if (SaTokenAuthIgnoreUtil.isIgnore()) { + chain.doChain(); + return; + } Method method = chain.getCallingMethod(); SaCheckRole at = method.getAnnotation(SaCheckRole.class); SaManager.getStpLogic(at.type()).checkByAnnotation(at); diff --git a/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaTokenAuthIgnoreUtil.java b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaTokenAuthIgnoreUtil.java new file mode 100644 index 00000000..985a40d3 --- /dev/null +++ b/src/main/java/com/budwk/app/web/commons/auth/satoken/aop/SaTokenAuthIgnoreUtil.java @@ -0,0 +1,60 @@ +package com.budwk.app.web.commons.auth.satoken.aop; + +import com.budwk.app.web.commons.base.Globals; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.mvc.Mvcs; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.regex.Pattern; + +/** + * Sa-Token 注解认证白名单工具。 + *

+ * 用于集中维护不需要登录、权限、角色校验即可访问的 URL,匹配规则与旧 Shiro 体系中的 + * authIgnoreUrlArr 保持一致:数组中的每一项都按正则表达式与当前请求 URI 完整匹配。 + */ +public class SaTokenAuthIgnoreUtil { + + /** + * 不需要认证授权的 URL。 + *

+ * 参数说明:数组中的字符串为请求 URI 正则表达式,匹配的是去除项目 contextPath 后的路径。 + * 返回值说明:通过 {@link #isIgnore()} 返回 boolean,true 表示当前请求跳过 Sa-Token 注解校验。 + */ + private static final String[] AUTH_IGNORE_URL_ARR = Lang.array("/", + "/platform/activity/basic/scope/getScopeUser", + "/platform/fitnessWalk/stepManage/getActivityDateStep", + "/platform/fitnessWalk/stepManage/winningRecord", + "/platform/fitnessWalk/stepManage/updateStepMonth", + "/platform/fitnessWalk/stepRanking/getUserStepRanking", + "/platform/fitnessWalk/stepManage/getActivityQualifyProgressBar", + "/platform/fitnessWalk/stepWining/getUserStepWining", + "/platform/fitnessWalk/common/getIssueById", + "/platform/fitnessWalk/common/saveAnswer", + "/platform/fitnessWalk/stepWining/prizeOption", + "/platform/fitnessWalk/stepWining/prizeUsers", + "/platform/fitnessWalk/punchLottery/judgeWinningToPunch", + "/platform/fitnessWalk/punchLottery/getLotteryRecord", + "/platform/fitnessWalk/punchLottery/doExchange", + "/platform/fitnessWalk/punchLottery/getPunchWining", + "/platform/fitnessWalk/punchLottery/doReadLottery", + "/platform/fitnessWalk/activityRelation/isCurrentUserRelationActivityQualified", + "/platform/fitnessWalk/welfare/addWelfareList", + "/platform/fitnessWalk/weapp/.*"); + + /** + * 判断当前请求是否命中匿名访问白名单。 + * + * @return boolean true 表示当前 URL 不需要执行登录、权限、角色注解校验;false 表示继续走原有 Sa-Token 校验逻辑 + */ + public static boolean isIgnore() { + HttpServletRequest request = Mvcs.getReq(); + if (request == null) { + return false; + } + String requestURI = Strings.sNull(request.getRequestURI()).replaceFirst("^" + Pattern.quote(Strings.sNull(Globals.AppBase)), ""); + return Arrays.stream(AUTH_IGNORE_URL_ARR).anyMatch(v -> Pattern.compile(v).matcher(requestURI).matches()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionManageController.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionManageController.java index 171a07e5..7b6fad30 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionManageController.java @@ -162,27 +162,10 @@ public class ActivityWorksCollectionManageController { @SaCheckPermission(value = {"activity.workscollection.manage", "activity.workscollection.new"}, mode = SaMode.OR) @Aop(TransAop.READ_COMMITTED) public Result update(@Param("data") @Valid Activity_works_collection worksCollection) { - String validateMessage = activityWorksCollectionService.validateReferencedTypesBeforeUpdate(worksCollection); + String validateMessage = activityWorksCollectionService.updatePreservingTypeIds(worksCollection); if (StrUtil.isNotBlank(validateMessage)) { return Result.error(validateMessage); } - dao.update(worksCollection); - dao.updateLinks(worksCollection, "subjectTypes"); - dao.insertLinks(worksCollection, "subjectTypes"); - //清除页面已经删除的 - dao.clear(Activity_works_subjectType.class, - Cnd.where(Activity_works_subjectType::getActivityId, "=", worksCollection.getId()) - .andEX("id", "not in", worksCollection.getSubjectTypes().stream().map(Activity_works_subjectType::getId).toList())); - - worksCollection.getSubjectTypes().forEach(item -> { - dao.updateLinks(item, "worksTypes"); - dao.insertLinks(item, "worksTypes"); - //清除页面已经删除的 - List workIds = item.getWorksTypes().stream().map(Activity_works_worksType::getId).toList(); - dao.clear(Activity_works_worksType.class, - Cnd.where(Activity_works_worksType::getId, "not in ", workIds) - .and(Activity_works_worksType::getSubjectId,"=",item.getId())); - }); syncHomeActivity(worksCollection); return Result.success(); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/ActivityWorksCollectionService.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/ActivityWorksCollectionService.java index dd51d859..ed41c9d5 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/ActivityWorksCollectionService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/ActivityWorksCollectionService.java @@ -35,6 +35,14 @@ public interface ActivityWorksCollectionService extends BaseService submittedSubjectTypes = CollUtil.defaultIfEmpty( + worksCollection.getSubjectTypes(), Collections.emptyList()); + List persistedSubjectTypes = dao.query(Activity_works_subjectType.class, + Cnd.where(Activity_works_subjectType::getActivityId, "=", worksCollection.getId())); + Map persistedSubjectMap = persistedSubjectTypes.stream() + .collect(Collectors.toMap(Activity_works_subjectType::getId, item -> item)); + + Set submittedSubjectIds = new HashSet<>(); + for (Activity_works_subjectType subjectType : submittedSubjectTypes) { + if (subjectType == null) { + return "主题类型数据不能为空"; + } + if (StrUtil.isNotBlank(subjectType.getId())) { + if (!persistedSubjectMap.containsKey(subjectType.getId())) { + return "主题类型数据已发生变化,请刷新页面后重新编辑"; + } + if (!submittedSubjectIds.add(subjectType.getId())) { + return "主题类型数据重复,请刷新页面后重新编辑"; + } + } + + List submittedWorksTypes = CollUtil.defaultIfEmpty( + subjectType.getWorksTypes(), Collections.emptyList()); + if (StrUtil.isBlank(subjectType.getId())) { + boolean containsPersistedWorksType = submittedWorksTypes.stream() + .anyMatch(worksType -> worksType != null && StrUtil.isNotBlank(worksType.getId())); + if (containsPersistedWorksType) { + return "新增主题不能关联原有作品类型,请刷新页面后重新编辑"; + } + continue; + } + + List persistedWorksTypes = dao.query(Activity_works_worksType.class, + Cnd.where(Activity_works_worksType::getSubjectId, "=", subjectType.getId())); + Map persistedWorksTypeMap = persistedWorksTypes.stream() + .collect(Collectors.toMap(Activity_works_worksType::getId, item -> item)); + Set submittedWorksIds = new HashSet<>(); + for (Activity_works_worksType worksType : submittedWorksTypes) { + if (worksType == null) { + return "作品类型数据不能为空"; + } + if (StrUtil.isNotBlank(worksType.getId()) && !persistedWorksTypeMap.containsKey(worksType.getId())) { + return "作品类型数据已发生变化,请刷新页面后重新编辑"; + } + if (StrUtil.isNotBlank(worksType.getId()) && !submittedWorksIds.add(worksType.getId())) { + return "作品类型数据重复,请刷新页面后重新编辑"; + } + } + } + + String validateMessage = validateReferencedTypesBeforeUpdate(worksCollection); + if (StrUtil.isNotBlank(validateMessage)) { + return validateMessage; + } + + dao.update(worksCollection); + for (Activity_works_subjectType subjectType : submittedSubjectTypes) { + subjectType.setActivityId(worksCollection.getId()); + if (StrUtil.isBlank(subjectType.getId())) { + dao.insert(subjectType); + } else { + dao.update(subjectType); + } + submittedSubjectIds.add(subjectType.getId()); + + List submittedWorksTypes = CollUtil.defaultIfEmpty( + subjectType.getWorksTypes(), Collections.emptyList()); + Set retainedWorksIds = new HashSet<>(); + for (Activity_works_worksType worksType : submittedWorksTypes) { + worksType.setSubjectId(subjectType.getId()); + if (StrUtil.isBlank(worksType.getId())) { + dao.insert(worksType); + } else { + dao.update(worksType); + } + retainedWorksIds.add(worksType.getId()); + } + clearRemovedWorksTypes(subjectType.getId(), retainedWorksIds); + } + clearRemovedSubjectTypes(worksCollection.getId(), submittedSubjectIds); + return null; + } + + /** + * 删除页面已移除且未被投稿引用的作品类型;空集合表示删除当前主题下全部原有类型。 + */ + private void clearRemovedWorksTypes(String subjectId, Set retainedWorksIds) { + Cnd cnd = Cnd.where(Activity_works_worksType::getSubjectId, "=", subjectId); + if (CollUtil.isNotEmpty(retainedWorksIds)) { + cnd.and(Activity_works_worksType::getId, "not in", retainedWorksIds); + } + dao.clear(Activity_works_worksType.class, cnd); + } + + /** + * 删除页面已移除且未被投稿引用的主题类型;空集合表示删除当前活动全部原有主题。 + */ + private void clearRemovedSubjectTypes(String activityId, Set retainedSubjectIds) { + Cnd cnd = Cnd.where(Activity_works_subjectType::getActivityId, "=", activityId); + if (CollUtil.isNotEmpty(retainedSubjectIds)) { + cnd.and(Activity_works_subjectType::getId, "not in", retainedSubjectIds); + } + List removedSubjectIds = dao.query(Activity_works_subjectType.class, cnd).stream() + .map(Activity_works_subjectType::getId) + .toList(); + if (CollUtil.isEmpty(removedSubjectIds)) { + return; + } + // 先删除未被投稿引用主题下的作品类型,避免产生作品类型孤儿数据。 + dao.clear(Activity_works_worksType.class, + Cnd.where(Activity_works_worksType::getSubjectId, "in", removedSubjectIds)); + dao.clear(Activity_works_subjectType.class, + Cnd.where(Activity_works_subjectType::getId, "in", removedSubjectIds)); + } + @Override public String validateReferencedTypesBeforeUpdate(Activity_works_collection worksCollection) { if (worksCollection == null || StrUtil.isBlank(worksCollection.getId())) { diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalSecondedController.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalSecondedController.java index ddd1f3c3..a5cebdc3 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalSecondedController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalSecondedController.java @@ -173,10 +173,7 @@ public class ProposalSecondedController { } ProposalSearchParam.buildSearch(cnd, pageForm); cnd.groupBy("t.id"); - // 用户未指定有效排序字段时,继续沿用原有任务创建时间倒序。 - if (!proposalCommonService.applySafePageOrder(cnd, pageForm, ORDER_COLUMNS)) { - cnd.desc("t.createdAt"); - } + cnd.desc("t.createdAt"); sql.setCondition(cnd); Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); return Result.success(pagination); diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java index 53f9cb7c..e38aa458 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java @@ -244,7 +244,7 @@ public class ProposalUnderTakeReplyController { @SaCheckPermission("proposal.unitReply") @ApiOperation("查询本单位可转办用户") public Result selectViceUser(@Param("keyword") @Valid String keyword) { - Sql sql = Sqls.create("select id,loginname,username from vw_user $condition"); + Sql sql = Sqls.create("select id,loginname,username,unitName from vw_user $condition"); Cnd cnd = Cnd.NEW(); cnd.andEX("unitId", "=", SecurityUtil.getUnitId()); cnd.andEX("id", "!=", SecurityUtil.getUserId()); diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/param/ProposalSearchParam.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/param/ProposalSearchParam.java index 0b94239e..ea439b8e 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/param/ProposalSearchParam.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/param/ProposalSearchParam.java @@ -79,7 +79,7 @@ public class ProposalSearchParam extends PageForm { if (StrUtil.isAllNotBlank(searchParam.getPageOrderName(), searchParam.getPageOrderBy())) { cnd.orderBy(searchParam.getPageOrderName(), PageUtil.getOrder(searchParam.getPageOrderBy())); } else { - cnd.asc("info.code"); + cnd.desc("info.code"); } } } diff --git a/src/main/resources/views/platform/zhgh/democratic/proposal/transact/unitReply/index.html b/src/main/resources/views/platform/zhgh/democratic/proposal/transact/unitReply/index.html index 30972cfb..65700839 100644 --- a/src/main/resources/views/platform/zhgh/democratic/proposal/transact/unitReply/index.html +++ b/src/main/resources/views/platform/zhgh/democratic/proposal/transact/unitReply/index.html @@ -179,16 +179,17 @@ layout("/layouts/platform.html"){ - - - + + + + + + + + + + + diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html index 0933ab31..65afa20f 100644 --- a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html +++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html @@ -444,7 +444,7 @@ layout("/layouts/platform_h5.html"){ -