diff --git a/.gitignore b/.gitignore index 9193b5f3..7fbc1b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -324,4 +324,5 @@ docs/变更管理/ 移动端违纪记录模块开发规范.md .playwright-mcp/ 查找界面中涉及到的权限字符.md -docs/部署文档/nginx配置/hzdyjsweb.camasort.com.conf \ No newline at end of file +docs/部署文档/nginx配置/hzdyjsweb.camasort.com.conf +首页完善的提示词.md \ No newline at end of file diff --git a/backend/pom.xml b/backend/pom.xml index c5e7d7cf..3f903412 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -31,7 +31,7 @@ 2.2.7 4.3.1 1.5.0 - 1.4.8 + 1.5.0 0.2.0 1.18.36 1.80 diff --git a/backend/ruoyi-admin/pom.xml b/backend/ruoyi-admin/pom.xml index 2e838024..e8ab5226 100644 --- a/backend/ruoyi-admin/pom.xml +++ b/backend/ruoyi-admin/pom.xml @@ -157,11 +157,11 @@ - + de.codecentric diff --git a/backend/ruoyi-modules/pom.xml b/backend/ruoyi-modules/pom.xml index 17b30897..c999a351 100644 --- a/backend/ruoyi-modules/pom.xml +++ b/backend/ruoyi-modules/pom.xml @@ -25,7 +25,7 @@ ruoyi-jcbt ruoyi-bzrkh ruoyi-xskh - + ruoyi-stgl ruoyi-modules diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityAttendanceController.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityAttendanceController.java index 8fa069e1..6fba17bc 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityAttendanceController.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityAttendanceController.java @@ -22,6 +22,7 @@ import org.dromara.stgl.domain.bo.StglActivityAttendanceBo; import org.dromara.stgl.service.IStglActivityAttendanceService; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; +import org.apache.commons.lang3.StringUtils; /** * 活动考勤签到 @@ -120,6 +121,28 @@ public class StglActivityAttendanceController extends BaseController { return R.ok(stglActivityAttendanceService.queryByActivityAndUser(activityId, userId)); } + /** + * 根据活动ID和用户ID查询所有签到记录(支持多次签到) + */ + @SaCheckPermission("stgl:activityAttendance:query") + @GetMapping("/getAllByActivityAndUser") + public R> getAllByActivityAndUser( + @RequestParam("activityId") Long activityId, + @RequestParam(value = "userId", required = false) Long userId, + @RequestParam(value = "studentNo", required = false) String studentNo) { + + List list; + if (userId != null) { + list = stglActivityAttendanceService.queryAllByActivityAndUser(activityId, userId); + } else if (StringUtils.isNotBlank(studentNo)) { + list = stglActivityAttendanceService.queryAllByActivityAndStudentNo(activityId, studentNo); + } else { + return R.fail("请提供用户ID或学号"); + } + + return R.ok(list); + } + /** * 用户签到 */ @@ -128,8 +151,7 @@ public class StglActivityAttendanceController extends BaseController { @RepeatSubmit() @PostMapping("/signIn") public R signIn(@Validated @RequestBody StglActivityAttendanceBo bo) { - // 设置当前登录用户ID - bo.setUserId(LoginHelper.getUserId()); + // 移除重复设置userId,让Service层通过学号查找用户ID return toAjax(stglActivityAttendanceService.signIn(bo)); } @@ -141,8 +163,7 @@ public class StglActivityAttendanceController extends BaseController { @RepeatSubmit() @PostMapping("/signOut") public R signOut(@Validated @RequestBody StglActivityAttendanceBo bo) { - // 设置当前登录用户ID - bo.setUserId(LoginHelper.getUserId()); + // 移除重复设置userId,让Service层通过学号查找用户ID return toAjax(stglActivityAttendanceService.signOut(bo)); } } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityRegisterController.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityRegisterController.java index 73380af9..e8f65219 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityRegisterController.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglActivityRegisterController.java @@ -15,7 +15,7 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.web.core.BaseController; -import org.dromara.stgl.domain.bo.BatchApprovalBo; +import org.dromara.stgl.domain.bo.StglBatchApprovalBo; import org.dromara.stgl.domain.bo.StglActivityRegistrationBo; import org.dromara.stgl.domain.vo.StglActivityRegistrationVo; import org.dromara.stgl.service.IStglActivityRegistrationService; @@ -120,7 +120,7 @@ public class StglActivityRegisterController extends BaseController { @SaCheckPermission("stgl:activityRegister:approve") @Log(title = "活动报名批量审核", businessType = BusinessType.UPDATE) @PostMapping("/batchApprove") - public R batchApprove(@Validated @RequestBody BatchApprovalBo batchApprovalBo) { + public R batchApprove(@Validated @RequestBody StglBatchApprovalBo batchApprovalBo) { return toAjax(stglActivityRegistrationService.batchApprove(batchApprovalBo.getIds(), batchApprovalBo.getApprovalStatus(), batchApprovalBo.getApprovalRemark(), LoginHelper.getUserId())); } diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglClubController.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglClubController.java index f0bed731..da516a50 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglClubController.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglClubController.java @@ -228,6 +228,21 @@ public class StglClubController extends BaseController { return toAjax(stglClubService.changeStatus(id, status)); } + /** + * 修改社团报名开启状态 + */ + @Operation(summary = "修改社团报名开启状态") + @SaCheckPermission("stgl:club:edit") + @Log(title = "社团信息", businessType = BusinessType.UPDATE) + @PutMapping("/changeSighOpenStatus") + @Parameters({ + @Parameter(name = "id", description = "社团ID", required = true), + @Parameter(name = "sighOpen", description = "报名开启状态(Y/N)", required = true) + }) + public R changeSighOpenStatus(@RequestParam Long id, @RequestParam String sighOpen) { + return toAjax(stglClubService.changeSighOpenStatus(id, sighOpen)); + } + /** * 修复已存在社团的成员记录 * 为缺失社长、副社长成员记录的社团补充相应记录 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerMemberController.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerMemberController.java index 1c05da0f..aef0ef40 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerMemberController.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerMemberController.java @@ -92,7 +92,7 @@ public class StglVolunteerMemberController extends BaseController { bo.setMemberType(2); // 志愿者成员 // 如果前端没有传递roleType,设置默认值为1(队员) if (bo.getRoleType() == null) { - bo.setRoleType(1); + bo.setRoleType("1"); } return toAjax(stglMemberService.insertByBo(bo)); } diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerTeamController.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerTeamController.java index 5ba798d2..0ec9dc78 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerTeamController.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/controller/StglVolunteerTeamController.java @@ -302,4 +302,14 @@ public class StglVolunteerTeamController extends BaseController { return toAjax(stglVolunteerTeamService.transferVolunteerTeam(id, newLeaderUserId)); } + + /** + * 修改志愿者团队报名开启状态 + */ + @SaCheckPermission("stgl:volunteerTeam:edit") + @Log(title = "志愿者团队报名状态变更", businessType = BusinessType.UPDATE) + @PutMapping("/changeSighOpenStatus") + public R changeSighOpenStatus(@RequestParam Long id, @RequestParam String sighOpen) { + return toAjax(stglVolunteerTeamService.changeSighOpenStatus(id, sighOpen)); + } } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivityAttendance.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivityAttendance.java index 97a72de4..35267d56 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivityAttendance.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivityAttendance.java @@ -126,4 +126,10 @@ public class StglActivityAttendance extends TenantEntity { * 签到状态(0-未签到 1-已签到 2-已签退) */ private Integer overallStatus; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic(value = "0", delval = "1") + private Integer deleted; } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglClub.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglClub.java index a366a298..a6d3b4e9 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglClub.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglClub.java @@ -192,6 +192,11 @@ public class StglClub extends TenantEntity { */ private Integer status; + /** + * 开启报名(Y是 N否) + */ + private String sighOpen; + /** * 备注 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglMember.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglMember.java index 910d625f..a3b38636 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglMember.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglMember.java @@ -53,9 +53,9 @@ public class StglMember extends TenantEntity { private String studentName; /** - * 角色类型(1-社长 2-副社长 3-部长 4-普通成员) + * 角色类型(社长、副社长、部长、普通成员) */ - private Integer roleType; + private String roleType; /** * 加入时间 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglVolunteerTeam.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglVolunteerTeam.java index 92ae8960..52004aa2 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglVolunteerTeam.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglVolunteerTeam.java @@ -127,4 +127,9 @@ public class StglVolunteerTeam extends TenantEntity { */ private Integer status; + /** + * 报名开启状态(Y-开启 N-关闭) + */ + private String sighOpen; + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/BatchApprovalBo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/BatchApprovalBo.java deleted file mode 100644 index 594236f1..00000000 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/BatchApprovalBo.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.dromara.stgl.domain.bo; - -import lombok.Data; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Size; - -import java.util.List; - -/** - * 批量审核请求对象 - * - * @author ruoyi - * @date 2025-01-31 - */ -@Data -public class BatchApprovalBo { - - /** - * 报名ID数组 - */ - @NotEmpty(message = "审核ID列表不能为空") - private List ids; - - /** - * 审核状态 1-通过 2-驳回 - */ - @NotNull(message = "审核状态不能为空") - @Min(value = 1, message = "审核状态值无效") - @Max(value = 2, message = "审核状态值无效") - private Integer approvalStatus; - - /** - * 审核意见 - */ - @Size(max = 500, message = "审核意见不能超过500个字符") - private String approvalRemark; -} \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglClubBo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglClubBo.java index 12792990..87540776 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglClubBo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglClubBo.java @@ -230,6 +230,11 @@ public class StglClubBo extends BaseEntity { */ private Integer status; + /** + * 开启报名(Y是 N否) + */ + private String sighOpen; + /** * 备注 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglMemberBo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglMemberBo.java index 8799e672..6c63606d 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglMemberBo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglMemberBo.java @@ -64,9 +64,7 @@ public class StglMemberBo extends BaseEntity { /** * 角色类型(社团:1-社长 2-副社长 3-部长 4-普通成员;志愿者:0-队长 1-队员) */ - @Min(value = 0, message = "角色类型值无效") - @Max(value = 4, message = "角色类型值无效") - private Integer roleType; + private String roleType; /** * 加入时间 @@ -76,7 +74,7 @@ public class StglMemberBo extends BaseEntity { /** * 状态(0-正常 1-停用) */ - private Integer status; + private String status; /** * 备注 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglVolunteerTeamBo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglVolunteerTeamBo.java index c4e348de..83d66b1c 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglVolunteerTeamBo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglVolunteerTeamBo.java @@ -150,4 +150,10 @@ public class StglVolunteerTeamBo extends BaseEntity { */ private Integer status; + /** + * 报名开启状态(Y-开启 N-关闭) + */ + @Pattern(regexp = "^[YN]$", message = "报名开启状态只能为Y或N") + private String sighOpen; + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubRegisterVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubRegisterVo.java index cb94fcb1..01cf1ee3 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubRegisterVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubRegisterVo.java @@ -238,4 +238,9 @@ public class StglClubRegisterVo implements Serializable { */ private String remark; + /** + * 开启报名(Y是 N否) + */ + private String sighOpen; + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubVo.java index 1af9f43e..40650f20 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClubVo.java @@ -226,6 +226,12 @@ public class StglClubVo implements Serializable { @ExcelProperty(value = "状态") private Integer status; + /** + * 开启报名(Y是 N否) + */ + @ExcelProperty(value = "开启报名") + private String sighOpen; + /** * 备注 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglMemberVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglMemberVo.java index 89ace271..ea54f2b5 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglMemberVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglMemberVo.java @@ -112,7 +112,7 @@ public class StglMemberVo implements Serializable { /** * 角色类型(1-社长 2-副社长 3-成员) */ - private Integer roleType; + private String roleType; /** * 角色类型名称 @@ -130,7 +130,7 @@ public class StglMemberVo implements Serializable { /** * 状态(0-正常 1-停用) */ - private Integer status; + private String status; /** * 状态名称 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglVolunteerTeamVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglVolunteerTeamVo.java index 0db73c57..77126384 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglVolunteerTeamVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglVolunteerTeamVo.java @@ -149,6 +149,12 @@ public class StglVolunteerTeamVo implements Serializable { @ExcelProperty(value = "状态") private Integer status; + /** + * 报名开启状态(Y-开启 N-关闭) + */ + @ExcelProperty(value = "报名开启状态") + private String sighOpen; + /** * 创建者 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/listener/StglMemberImportListener.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/listener/StglMemberImportListener.java index a49c672c..0cb27563 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/listener/StglMemberImportListener.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/listener/StglMemberImportListener.java @@ -273,10 +273,10 @@ public class StglMemberImportListener extends AnalysisEventListener selectAllByActivityAndUser(@Param("activityId") Long activityId, @Param("userId") Long userId); + /** * 根据ID查询活动考勤签到详情(关联查询活动信息) * diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/mapper/StglMemberMapper.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/mapper/StglMemberMapper.java index fcb1ccac..7deb36ce 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/mapper/StglMemberMapper.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/mapper/StglMemberMapper.java @@ -36,17 +36,19 @@ public interface StglMemberMapper extends BaseMapperPlus selectMemberWithUserInfo(@Param("memberType") Integer memberType, @Param("relationId") Long relationId, @Param("studentNo") String studentNo, @Param("studentName") String studentName, - @Param("roleType") Integer roleType, - @Param("status") Integer status, + @Param("roleType") String roleType, + @Param("status") String status, @Param("clubName") String clubName, @Param("teamName") String teamName, - @Param("userId") Long userId); + @Param("userId") Long userId, + @Param("params") java.util.Map params); /** * 检查用户是否已加入某个社团/志愿者队伍 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglActivityAttendanceService.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglActivityAttendanceService.java index cf500bce..bd437768 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglActivityAttendanceService.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglActivityAttendanceService.java @@ -56,6 +56,16 @@ public interface IStglActivityAttendanceService { */ StglActivityAttendanceVo queryByActivityAndUser(Long activityId, Long userId); + /** + * 根据活动ID和用户ID查询所有签到记录(支持多次签到) + */ + List queryAllByActivityAndUser(Long activityId, Long userId); + + /** + * 根据活动ID和学号查询所有签到记录(支持多次签到) + */ + List queryAllByActivityAndStudentNo(Long activityId, String studentNo); + /** * 用户签到 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglClubService.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglClubService.java index 02397e69..ef0e6cb8 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglClubService.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglClubService.java @@ -106,6 +106,15 @@ public interface IStglClubService { */ Boolean changeStatus(Long id, Integer status); + /** + * 修改社团报名开启状态 + * + * @param id 社团ID + * @param sighOpen 报名开启状态(Y/N) + * @return 是否操作成功 + */ + Boolean changeSighOpenStatus(Long id, String sighOpen); + /** * 修复所有已存在社团的成员记录 * 为那些没有对应成员记录的社长和副社长补充成员记录 diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglVolunteerTeamService.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglVolunteerTeamService.java index 63e35e46..92954480 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglVolunteerTeamService.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/IStglVolunteerTeamService.java @@ -130,4 +130,13 @@ public interface IStglVolunteerTeamService { */ Integer fixExistingTeamLeaderRecords(); + /** + * 修改志愿者团队报名开启状态 + * + * @param id 团队ID + * @param sighOpen 报名开启状态(Y/N) + * @return 是否修改成功 + */ + Boolean changeSighOpenStatus(Long id, String sighOpen); + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityAttendanceServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityAttendanceServiceImpl.java index 1fc0408a..266badf7 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityAttendanceServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityAttendanceServiceImpl.java @@ -15,11 +15,14 @@ import org.dromara.stgl.domain.vo.StglActivityAttendanceVo; import org.dromara.stgl.domain.StglActivityAttendance; import org.dromara.stgl.mapper.StglActivityAttendanceMapper; import org.dromara.stgl.service.IStglActivityAttendanceService; +import org.dromara.system.domain.SysUser; +import org.dromara.system.mapper.SysUserMapper; import java.util.List; import java.util.Map; import java.util.Collection; import java.util.Date; +import java.util.ArrayList; /** * 活动考勤签到Service业务层处理 @@ -32,6 +35,7 @@ import java.util.Date; public class StglActivityAttendanceServiceImpl implements IStglActivityAttendanceService { private final StglActivityAttendanceMapper baseMapper; + private final SysUserMapper sysUserMapper; /** * 查询活动考勤签到 @@ -141,29 +145,51 @@ public class StglActivityAttendanceServiceImpl implements IStglActivityAttendanc return baseMapper.selectByActivityAndUser(activityId, userId); } + /** + * 根据活动ID和用户ID查询所有签到记录(支持多次签到) + */ + @Override + public List queryAllByActivityAndUser(Long activityId, Long userId) { + return baseMapper.selectAllByActivityAndUser(activityId, userId); + } + + /** + * 根据活动ID和学号查询所有签到记录(支持多次签到) + */ + @Override + public List queryAllByActivityAndStudentNo(Long activityId, String studentNo) { + // 先通过学号获取用户ID + Long userId = getUserIdByStudentNo(studentNo); + if (userId == null) { + return new ArrayList<>(); + } + return baseMapper.selectAllByActivityAndUser(activityId, userId); + } + /** * 用户签到 */ @Override public Boolean signIn(StglActivityAttendanceBo bo) { - // 检查是否已存在签到记录 - StglActivityAttendanceVo existingRecord = queryByActivityAndUser(bo.getActivityId(), bo.getUserId()); - - if (existingRecord != null) { - // 如果已存在记录,更新签到信息 - bo.setId(existingRecord.getId()); - bo.setSignInTime(new Date()); - bo.setSignInStatus(1); - bo.setOverallStatus(1); // 已签到 - return updateByBo(bo); - } else { - // 如果不存在记录,新增签到记录 - bo.setSignInTime(new Date()); - bo.setSignInStatus(1); - bo.setSignOutStatus(0); - bo.setOverallStatus(1); // 已签到 - return insertByBo(bo); + // 通过学号查找用户ID + Long userId = getUserIdByStudentNo(bo.getStudentNo()); + if (userId == null) { + throw new RuntimeException("未找到对应的用户信息"); } + + // 移除重复签到检查,允许每次签到都生成新记录 + // 无论之前是否有签到记录,都创建新的签到记录 + bo.setUserId(userId); + bo.setSignInTime(new Date()); + bo.setSignInStatus(1); + bo.setSignOutStatus(0); + bo.setOverallStatus(1); // 已签到 + + // 设置基础字段 + bo.setCreateTime(new Date()); + bo.setUpdateTime(new Date()); + + return insertByBo(bo); } /** @@ -171,18 +197,82 @@ public class StglActivityAttendanceServiceImpl implements IStglActivityAttendanc */ @Override public Boolean signOut(StglActivityAttendanceBo bo) { - // 必须先签到才能签退 - StglActivityAttendanceVo existingRecord = queryByActivityAndUser(bo.getActivityId(), bo.getUserId()); - - if (existingRecord == null || existingRecord.getSignInStatus() != 1) { - throw new RuntimeException("请先完成签到"); + // 通过学号查找用户ID + Long userId = getUserIdByStudentNo(bo.getStudentNo()); + if (userId == null) { + throw new RuntimeException("未找到对应的用户信息"); } - // 更新签退信息 - bo.setId(existingRecord.getId()); - bo.setSignOutTime(new Date()); - bo.setSignOutStatus(1); - bo.setOverallStatus(2); // 已签退 - return updateByBo(bo); + // 如果提供了记录ID,直接更新该记录 + if (bo.getId() != null) { + StglActivityAttendance record = baseMapper.selectById(bo.getId()); + if (record == null) { + throw new RuntimeException("没有找到指定的签到记录"); + } + + // 检查是否可以签退 + if (record.getSignInStatus() != 1) { + throw new RuntimeException("您还未完成签到,不能签退"); + } + + if (record.getSignOutStatus() == 1) { + throw new RuntimeException("您已经完成签退,无需重复签退"); + } + + // 更新签退信息 + bo.setUserId(userId); + bo.setSignOutTime(new Date()); + bo.setSignOutStatus(1); + bo.setOverallStatus(2); // 已签退 + return updateByBo(bo); + } else { + // 如果没有提供记录ID,查找最新的未完成签到记录 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(StglActivityAttendance::getActivityId, bo.getActivityId()); + queryWrapper.eq(StglActivityAttendance::getUserId, userId); + queryWrapper.orderByDesc(StglActivityAttendance::getCreateTime); + queryWrapper.last("LIMIT 1"); + + StglActivityAttendance record = baseMapper.selectOne(queryWrapper); + + if (record == null) { + throw new RuntimeException("没有找到签到记录,请先完成签到"); + } + + // 检查是否可以签退 + if (record.getSignInStatus() != 1) { + throw new RuntimeException("您还未完成签到,不能签退"); + } + + if (record.getSignOutStatus() == 1) { + throw new RuntimeException("您已经完成签退,无需重复签退"); + } + + // 更新签退信息 + bo.setId(record.getId()); + bo.setUserId(userId); + bo.setSignOutTime(new Date()); + bo.setSignOutStatus(1); + bo.setOverallStatus(2); // 已签退 + return updateByBo(bo); + } + } + + /** + * 根据学号获取用户ID + */ + private Long getUserIdByStudentNo(String studentNo) { + if (StringUtils.isBlank(studentNo)) { + return null; + } + + // 这里需要根据实际的用户表结构来查询 + // 假设用户表是sys_user,学号字段是user_name + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getUserName, studentNo); + wrapper.eq(SysUser::getDelFlag, "0"); + + SysUser user = sysUserMapper.selectOne(wrapper); + return user != null ? user.getUserId() : null; } } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityServiceImpl.java index 1347b651..b242ec9e 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglActivityServiceImpl.java @@ -21,16 +21,27 @@ import org.dromara.stgl.domain.bo.StglActivityBo; import org.dromara.stgl.domain.vo.StglActivityVo; import org.dromara.stgl.mapper.StglActivityMapper; import org.dromara.stgl.service.IStglActivityService; +import org.dromara.stgl.utils.AdvisorRoleAssigner; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import org.dromara.common.json.utils.JsonUtils; +import com.fasterxml.jackson.core.type.TypeReference; +import org.dromara.stgl.domain.StglClub; +import org.dromara.stgl.domain.StglVolunteerTeam; +import org.dromara.stgl.mapper.StglClubMapper; +import org.dromara.stgl.mapper.StglVolunteerTeamMapper; /** * 活动信息Service业务层处理 @@ -38,11 +49,15 @@ import java.util.concurrent.atomic.AtomicInteger; * @author ruoyi * @date 2025-01-07 */ +@Slf4j @RequiredArgsConstructor @Service public class StglActivityServiceImpl extends ServiceImpl implements IStglActivityService { private final StglActivityMapper baseMapper; + private final AdvisorRoleAssigner advisorRoleAssigner; + private final StglClubMapper stglClubMapper; + private final StglVolunteerTeamMapper stglVolunteerTeamMapper; /** * 查询活动信息 @@ -57,6 +72,9 @@ public class StglActivityServiceImpl extends ServiceImpl queryPageList(StglActivityBo bo, PageQuery pageQuery) { + // 应用数据权限控制 + applyDataScope(bo); + // 转换为实体对象,使用自定义SQL查询(包含关联信息) StglActivity activity = BeanUtil.toBean(bo, StglActivity.class); Page result = baseMapper.selectVoPage(pageQuery.build(), activity); @@ -68,6 +86,9 @@ public class StglActivityServiceImpl extends ServiceImpl queryList(StglActivityBo bo) { + // 应用数据权限控制 + applyDataScope(bo); + // 转换为实体对象,使用自定义SQL查询(包含关联信息) StglActivity activity = BeanUtil.toBean(bo, StglActivity.class); List list = baseMapper.selectVoList(activity); @@ -215,6 +236,8 @@ public class StglActivityServiceImpl extends ServiceImpl 0; if (flag) { bo.setId(add.getId()); + // 为指导老师分配角色 + assignAdvisorRoles(add); } return flag; } @@ -227,7 +250,21 @@ public class StglActivityServiceImpl extends ServiceImpl 0; + + // 获取更新前的活动信息,用于比较指导老师变化 + StglActivity oldActivity = null; + if (update.getId() != null) { + oldActivity = baseMapper.selectById(update.getId()); + } + + boolean updateResult = baseMapper.updateById(update) > 0; + + if (updateResult) { + // 处理指导老师角色分配 + handleAdvisorRoleAssignment(oldActivity, update); + } + + return updateResult; } /** @@ -382,4 +419,219 @@ public class StglActivityServiceImpl extends ServiceImpl 0; } + /** + * 为指导老师分配角色 + * + * @param activity 活动信息 + */ + private void assignAdvisorRoles(StglActivity activity) { + try { + List advisorUserIds = extractAdvisorUserIds(activity); + if (!advisorUserIds.isEmpty()) { + advisorRoleAssigner.assignAdvisorRole(advisorUserIds); + log.info("成功为活动 {} 的指导老师分配角色,指导老师数量: {}", activity.getActivityName(), advisorUserIds.size()); + } + } catch (Exception e) { + log.error("为活动 {} 的指导老师分配角色时发生异常: {}", activity.getActivityName(), e.getMessage()); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 处理指导老师角色分配(更新时使用) + * + * @param oldActivity 更新前的活动信息 + * @param newActivity 更新后的活动信息 + */ + private void handleAdvisorRoleAssignment(StglActivity oldActivity, StglActivity newActivity) { + try { + // 获取更新前后的指导老师用户ID列表 + List oldAdvisorUserIds = oldActivity != null ? extractAdvisorUserIds(oldActivity) : new ArrayList<>(); + List newAdvisorUserIds = extractAdvisorUserIds(newActivity); + + // 找出新增的指导老师 + List addedAdvisorUserIds = newAdvisorUserIds.stream() + .filter(id -> !oldAdvisorUserIds.contains(id)) + .collect(Collectors.toList()); + + // 找出移除的指导老师 + List removedAdvisorUserIds = oldAdvisorUserIds.stream() + .filter(id -> !newAdvisorUserIds.contains(id)) + .collect(Collectors.toList()); + + // 为新指导老师分配角色 + if (!addedAdvisorUserIds.isEmpty()) { + advisorRoleAssigner.assignAdvisorRole(addedAdvisorUserIds); + log.info("活动 {} 新增指导老师,成功分配角色,数量: {}", newActivity.getActivityName(), addedAdvisorUserIds.size()); + } + + // 移除旧指导老师的角色 + if (!removedAdvisorUserIds.isEmpty()) { + advisorRoleAssigner.removeAdvisorRoles(removedAdvisorUserIds); + log.info("活动 {} 移除指导老师,成功移除角色,数量: {}", newActivity.getActivityName(), removedAdvisorUserIds.size()); + } + } catch (Exception e) { + log.error("处理活动 {} 的指导老师角色分配时发生异常: {}", newActivity.getActivityName(), e.getMessage()); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 从活动信息中提取指导老师用户ID列表 + * + * @param activity 活动信息 + * @return 指导老师用户ID列表 + */ + private List extractAdvisorUserIds(StglActivity activity) { + List advisorUserIds = new ArrayList<>(); + + try { + // 从JSON字段读取指导老师数据 + if (StringUtils.isNotBlank(activity.getInstructors())) { + List> instructors = JsonUtils.parseObject(activity.getInstructors(), new TypeReference>>() {}); + for (Map instructor : instructors) { + // 修复:支持嵌套的JSON结构,从teacher子对象中提取userId + Object userIdObj = null; + + // 尝试直接从instructor对象获取userId(兼容旧格式) + if (instructor.containsKey("userId")) { + userIdObj = instructor.get("userId"); + } + // 尝试从teacher子对象获取userId(新格式) + else if (instructor.containsKey("teacher")) { + Object teacherObj = instructor.get("teacher"); + if (teacherObj instanceof Map) { + @SuppressWarnings("unchecked") + Map teacher = (Map) teacherObj; + userIdObj = teacher.get("userId"); + } + } + + if (userIdObj != null) { + Long userId = Long.valueOf(userIdObj.toString()); + if (userId != null) { + advisorUserIds.add(userId); + } + } + } + } + } catch (Exception e) { + log.error("解析活动 {} 的指导老师数据时发生异常: {}", activity.getActivityName(), e.getMessage()); + } + + return advisorUserIds; + } + + /** + * 应用数据权限控制 + * 如果是stgl_president角色,只能查看自己创建的活动 + * 如果是stgl_instructor角色,只能查看自己作为指导老师的社团的活动 + * + * @param bo 查询条件 + */ + private void applyDataScope(StglActivityBo bo) { + try { + // 获取当前登录用户信息 + Long currentUserId = LoginHelper.getUserId(); + if (currentUserId == null) { + return; + } + + Set roleKeys = LoginHelper.getLoginUser().getRolePermission(); + + // 如果是stgl_president角色且不是管理员,只能查看自己创建的活动 + if (roleKeys.contains("stgl_president") && + !roleKeys.contains("admin") && + !roleKeys.contains("common")) { + + // 设置数据权限过滤条件 - 使用params.dataScope方式,与XML中的${activity.params.dataScope}对应 + if (bo.getParams() == null) { + bo.setParams(new HashMap<>()); + } + bo.getParams().put("dataScope", "AND sa.create_by = " + currentUserId); + log.info("应用数据权限:用户 {} 为社长角色,只能查看自己创建的活动", currentUserId); + } + + // 🔥 新增:如果是stgl_instructor角色且不是管理员,只能查看自己作为指导老师的社团的活动 + if (roleKeys.contains("stgl_instructor") && + !roleKeys.contains("admin") && + !roleKeys.contains("common")) { + + // 获取用户作为指导老师的社团ID列表 + List userAdvisorClubIds = getUserAdvisorClubIds(currentUserId); + + if (userAdvisorClubIds.isEmpty()) { + // 如果不是任何社团的指导老师,设置一个不存在的ID,返回空结果 + if (bo.getParams() == null) { + bo.setParams(new HashMap<>()); + } + bo.getParams().put("dataScope", "AND sa.related_club_id = -1"); + log.info("应用数据权限:用户 {} 为指导老师角色,但不是任何社团的指导老师,返回空结果", currentUserId); + } else { + // 设置数据权限过滤条件 - 只能查看自己作为指导老师的社团的活动 + if (bo.getParams() == null) { + bo.setParams(new HashMap<>()); + } + String clubIdsStr = userAdvisorClubIds.stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); + bo.getParams().put("dataScope", "AND sa.related_club_id IN (" + clubIdsStr + ")"); + log.info("应用数据权限:用户 {} 为指导老师角色,只能查看社团ID为 {} 的活动", currentUserId, clubIdsStr); + } + } + + } catch (Exception e) { + log.error("应用数据权限控制失败:{}", e.getMessage(), e); + } + } + + /** + * 获取用户作为指导老师的社团ID列表 + * + * @param userId 用户ID + * @return 社团ID列表 + */ + private List getUserAdvisorClubIds(Long userId) { + List clubIds = new ArrayList<>(); + + try { + // 从stgl_club表的advisors_json字段查询 + List jsonClubIds = getJsonAdvisorClubIds(userId); + clubIds.addAll(jsonClubIds); + + log.debug("用户 {} 作为指导老师的社团ID列表: {}", userId, clubIds); + + } catch (Exception e) { + log.error("获取用户 {} 作为指导老师的社团ID列表时发生异常: {}", userId, e.getMessage(), e); + } + + return clubIds; + } + + /** + * 从社团表的advisors_json字段获取用户作为指导老师的社团ID列表 + * + * @param userId 用户ID + * @return 社团ID列表 + */ + private List getJsonAdvisorClubIds(Long userId) { + List clubIds = new ArrayList<>(); + + try { + // 查询社团表中advisors_json字段包含该用户的记录 + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.select(StglClub::getId); + lqw.like(StglClub::getAdvisorsJson, userId.toString()); + + List clubs = stglClubMapper.selectList(lqw); + clubIds = clubs.stream() + .map(StglClub::getId) + .collect(Collectors.toList()); + + } catch (Exception e) { + log.error("从社团表获取用户 {} 作为指导老师的社团ID列表时发生异常: {}", userId, e.getMessage(), e); + } + + return clubIds; + } } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubRegisterServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubRegisterServiceImpl.java index 23552427..9fce9b6a 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubRegisterServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubRegisterServiceImpl.java @@ -79,6 +79,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { private LambdaQueryWrapper buildQueryWrapper(String clubType, String clubName) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(StglClub::getStatus, 0); // 只查询正常状态的社团(0-正常,1-停用) + lqw.eq(StglClub::getSighOpen, "Y"); // 只查询报名开启的社团 lqw.eq(StringUtils.isNotBlank(clubType), StglClub::getClubType, clubType); lqw.like(StringUtils.isNotBlank(clubName), StglClub::getClubName, clubName); lqw.orderByDesc(StglClub::getCreateTime); @@ -137,6 +138,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { // ========== 新增:章程文件和备注信息 ========== vo.setCharterUrl(club.getCharterUrl()); vo.setRemark(club.getRemark()); + vo.setSighOpen(club.getSighOpen()); // 设置报名开启状态 // 查询社团成员数量(所有已加入的成员) LambdaQueryWrapper memberCountLqw = Wrappers.lambdaQuery(); @@ -243,7 +245,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { member.setUserId(userId); member.setStudentNo(studentNo); member.setStudentName(studentName != null ? studentName : user.getNickName()); // 如果没有学生信息,使用用户昵称 - member.setRoleType(4); // 普通成员 + member.setRoleType("4"); // 普通成员 member.setJoinTime(new Date()); member.setStatus(0); // 待审核状态(stgl_member_status字典,新报名需审核) member.setRemark(reason); // 将申请理由存储到备注字段 @@ -272,7 +274,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { } // 检查是否是社长或副社长 - if (member.getRoleType() != null && member.getRoleType() <= 2) { + if (member.getRoleType() != null && Integer.parseInt(member.getRoleType()) <= 2) { throw new RuntimeException("社长和副社长不能直接退出,请先转让职务"); } diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubServiceImpl.java index 3a4ae5f7..51c81645 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglClubServiceImpl.java @@ -17,6 +17,7 @@ import org.dromara.stgl.domain.StglMember; import org.dromara.stgl.mapper.StglClubMapper; import org.dromara.stgl.mapper.StglMemberMapper; import org.dromara.stgl.service.IStglClubService; +import org.dromara.stgl.utils.AdvisorRoleAssigner; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.json.utils.JsonUtils; import com.fasterxml.jackson.core.type.TypeReference; @@ -35,10 +36,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import com.baomidou.mybatisplus.core.metadata.IPage; import java.util.Set; @@ -58,6 +61,8 @@ public class StglClubServiceImpl implements IStglClubService { private final StglMemberMapper memberMapper; // 添加学生信息Mapper private final XgStudentMsgMapper studentMsgMapper; + // 添加指导老师角色分配工具 + private final AdvisorRoleAssigner advisorRoleAssigner; /** * 查询社团信息 @@ -143,6 +148,31 @@ public class StglClubServiceImpl implements IStglClubService { bo.setClubIds(userClubIds); } } + + // 🔥 新增:如果是stgl_instructor角色且不是管理员,只能查看自己作为指导老师的社团 + if (roleKeys.contains("stgl_instructor") && + !roleKeys.contains("admin") && + !roleKeys.contains("common")) { + + // 获取用户作为指导老师的社团ID列表 + List userAdvisorClubIds = getUserAdvisorClubIds(currentUserId); + + if (userAdvisorClubIds.isEmpty()) { + // 如果不是任何社团的指导老师,设置一个不存在的ID,返回空结果 + bo.setClubIds(Collections.singletonList(-1L)); + } else { + // 如果之前已经设置了clubIds(比如stgl_president角色),则取交集 + if (CollectionUtils.isNotEmpty(bo.getClubIds())) { + List intersection = bo.getClubIds().stream() + .filter(userAdvisorClubIds::contains) + .collect(Collectors.toList()); + bo.setClubIds(intersection.isEmpty() ? Collections.singletonList(-1L) : intersection); + } else { + // 设置数据权限过滤条件 + bo.setClubIds(userAdvisorClubIds); + } + } + } } catch (Exception e) { // 如果获取权限信息失败,不影响正常查询 log.warn("获取用户权限信息失败: {}", e.getMessage()); @@ -164,7 +194,7 @@ public class StglClubServiceImpl implements IStglClubService { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(StglMember::getMemberType, 1) // 社团成员 .eq(StglMember::getUserId, userId) // 当前用户 - .eq(StglMember::getRoleType, 1) // 社长角色 + .eq(StglMember::getRoleType, "社长") // 社长角色 - 修复:使用字符串而不是数值 .eq(StglMember::getStatus, 2); // 已加入状态 List members = memberMapper.selectList(lqw); @@ -178,6 +208,91 @@ public class StglClubServiceImpl implements IStglClubService { } } + /** + * 获取用户作为指导老师的社团ID列表 + * + * @param userId 用户ID + * @return 社团ID列表 + */ + private List getUserAdvisorClubIds(Long userId) { + if (userId == null) { + return Collections.emptyList(); + } + + try { + // 方法1:从stgl_member表查询(如果指导老师作为成员记录) + LambdaQueryWrapper memberLqw = Wrappers.lambdaQuery(); + memberLqw.eq(StglMember::getMemberType, 1) // 社团成员 + .eq(StglMember::getUserId, userId) // 当前用户 + .eq(StglMember::getRoleType, "指导老师") // 指导老师角色 + .eq(StglMember::getStatus, 2); // 已加入状态 + + List memberAdvisors = memberMapper.selectList(memberLqw); + List memberClubIds = memberAdvisors.stream() + .map(StglMember::getRelationId) + .distinct() + .collect(Collectors.toList()); + + // 方法2:从社团表的advisors_json字段查询(主要方法) + LambdaQueryWrapper clubLqw = Wrappers.lambdaQuery(); + clubLqw.select(StglClub::getId, StglClub::getAdvisorsJson); + clubLqw.isNotNull(StglClub::getAdvisorsJson); + clubLqw.ne(StglClub::getAdvisorsJson, ""); + + List clubs = baseMapper.selectList(clubLqw); + List jsonClubIds = new ArrayList<>(); + + for (StglClub club : clubs) { + try { + if (StringUtils.isNotBlank(club.getAdvisorsJson())) { + List> advisors = JsonUtils.parseObject( + club.getAdvisorsJson(), + new TypeReference>>() {} + ); + + for (Map advisor : advisors) { + Object userIdObj = null; + + // 尝试直接从advisor对象获取userId + if (advisor.containsKey("userId")) { + userIdObj = advisor.get("userId"); + } + // 尝试从teacher子对象获取userId + else if (advisor.containsKey("teacher")) { + Object teacherObj = advisor.get("teacher"); + if (teacherObj instanceof Map) { + @SuppressWarnings("unchecked") + Map teacher = (Map) teacherObj; + userIdObj = teacher.get("userId"); + } + } + + if (userIdObj != null && userId.toString().equals(userIdObj.toString())) { + jsonClubIds.add(club.getId()); + break; // 找到该用户,继续下一个社团 + } + } + } + } catch (Exception e) { + log.warn("解析社团 {} 的指导老师JSON数据失败: {}", club.getId(), e.getMessage()); + } + } + + // 合并两种方法的结果 + Set allClubIds = new HashSet<>(); + allClubIds.addAll(memberClubIds); + allClubIds.addAll(jsonClubIds); + + log.info("用户 {} 作为指导老师的社团ID列表: memberClubIds={}, jsonClubIds={}, 最终结果={}", + userId, memberClubIds, jsonClubIds, allClubIds); + + return new ArrayList<>(allClubIds); + } catch (Exception e) { + log.error("查询用户作为指导老师的社团失败: {}", e.getMessage(), e); + return Collections.emptyList(); + } + } + private LambdaQueryWrapper buildQueryWrapper(StglClubBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); @@ -215,6 +330,8 @@ public class StglClubServiceImpl implements IStglClubService { bo.setId(add.getId()); // 自动创建社长和副社长的成员记录 createLeaderMemberRecords(add); + // 为指导老师分配角色 + assignAdvisorRoles(add); } return flag; } @@ -231,12 +348,20 @@ public class StglClubServiceImpl implements IStglClubService { StglClub update = MapstructUtils.convert(bo, StglClub.class); validEntityBeforeSave(update); + // 获取更新前的社团信息,用于比较指导老师变化 + StglClub oldClub = null; + if (update.getId() != null) { + oldClub = baseMapper.selectById(update.getId()); + } + // 更新社团基本信息 boolean updateResult = baseMapper.updateById(update) > 0; if (updateResult) { // 同步更新副社长的成员记录 syncVicePresidentsInMembers(update); + // 处理指导老师角色分配 + handleAdvisorRoleAssignment(oldClub, update); } return updateResult; @@ -358,6 +483,21 @@ public class StglClubServiceImpl implements IStglClubService { return baseMapper.updateById(club) > 0; } + /** + * 修改社团报名开启状态 + * + * @param id 社团ID + * @param sighOpen 报名开启状态(Y/N) + * @return 是否操作成功 + */ + @Override + public Boolean changeSighOpenStatus(Long id, String sighOpen) { + StglClub club = new StglClub(); + club.setId(id); + club.setSighOpen(sighOpen); + return baseMapper.updateById(club) > 0; + } + /** * 自动创建社长和副社长的成员记录 * @@ -373,7 +513,7 @@ public class StglClubServiceImpl implements IStglClubService { president.setRelationId(club.getId()); president.setStudentNo(club.getPresidentStudentNo()); president.setStudentName(club.getPresidentName()); - president.setRoleType(1); // 社长 + president.setRoleType("社长"); // 社长 president.setJoinTime(now); president.setStatus(2); // 已加入状态(stgl_member_status字典) president.setRemark("社团创建时自动添加"); @@ -482,7 +622,7 @@ public class StglClubServiceImpl implements IStglClubService { vicePresident.setRelationId(clubId); vicePresident.setStudentNo(studentNo); vicePresident.setStudentName(name); - vicePresident.setRoleType(2); // 副社长 + vicePresident.setRoleType("副社长"); // 副社长 vicePresident.setJoinTime(joinTime); vicePresident.setStatus(2); // 已加入状态(stgl_member_status字典) vicePresident.setRemark("社团创建时自动添加"); @@ -548,14 +688,14 @@ public class StglClubServiceImpl implements IStglClubService { // 检查并补充社长成员记录 if (StringUtils.isNotBlank(club.getPresidentStudentNo())) { - boolean presidentExists = checkMemberExists(club.getId(), club.getPresidentStudentNo(), 1); + boolean presidentExists = checkMemberExists(club.getId(), club.getPresidentStudentNo(), "社长"); if (!presidentExists) { StglMember president = new StglMember(); president.setMemberType(1); // 社团成员 president.setRelationId(club.getId()); president.setStudentNo(club.getPresidentStudentNo()); president.setStudentName(club.getPresidentName()); - president.setRoleType(1); // 社长 + president.setRoleType("社长"); // 社长 president.setJoinTime(club.getCreateTime() != null ? club.getCreateTime() : now); president.setStatus(2); // 已加入状态(stgl_member_status字典) president.setRemark("补充缺失的社长成员记录"); @@ -589,7 +729,7 @@ public class StglClubServiceImpl implements IStglClubService { // 1. 处理单个副社长字段(向后兼容) if (StringUtils.isNotBlank(club.getVicePresidentStudentNo())) { - boolean vicePresidentExists = checkMemberExists(club.getId(), club.getVicePresidentStudentNo(), 2); + boolean vicePresidentExists = checkMemberExists(club.getId(), club.getVicePresidentStudentNo(), "副社长"); if (!vicePresidentExists) { fixedCount += createFixedVicePresidentRecord( club.getId(), @@ -643,7 +783,7 @@ public class StglClubServiceImpl implements IStglClubService { if (StringUtils.isBlank(club.getVicePresidentStudentNo()) || !studentNo.equals(club.getVicePresidentStudentNo())) { - boolean exists = checkMemberExists(club.getId(), studentNo, 2); + boolean exists = checkMemberExists(club.getId(), studentNo, "副社长"); if (!exists) { System.out.println("修复副社长成员记录: " + name + "(" + studentNo + ")"); fixedCount += createFixedVicePresidentRecord(club.getId(), studentNo, name, joinTime) ? 1 : 0; @@ -677,7 +817,7 @@ public class StglClubServiceImpl implements IStglClubService { vicePresident.setRelationId(clubId); vicePresident.setStudentNo(studentNo); vicePresident.setStudentName(name); - vicePresident.setRoleType(2); // 副社长 + vicePresident.setRoleType("副社长"); // 副社长 vicePresident.setJoinTime(joinTime); vicePresident.setStatus(2); // 已加入状态(stgl_member_status字典) vicePresident.setRemark("补充缺失的副社长成员记录"); @@ -702,10 +842,11 @@ public class StglClubServiceImpl implements IStglClubService { * @param roleType 角色类型 * @return 是否存在 */ - private boolean checkMemberExists(Long clubId, String studentNo, Integer roleType) { + private boolean checkMemberExists(Long clubId, String studentNo, String roleType) { LambdaQueryWrapper query = Wrappers.lambdaQuery(); query.eq(StglMember::getMemberType, 1); query.eq(StglMember::getRelationId, clubId); + query.eq(StglMember::getMemberType, 1); query.eq(StglMember::getStudentNo, studentNo); query.eq(StglMember::getRoleType, roleType); query.eq(StglMember::getStatus, 1); @@ -721,11 +862,11 @@ public class StglClubServiceImpl implements IStglClubService { */ private void syncVicePresidentsInMembers(StglClub club) { try { - // 1. 删除现有的所有副社长记录(roleType = 2) + // 1. 删除现有的所有副社长记录(roleType = "副社长") LambdaQueryWrapper deleteWrapper = Wrappers.lambdaQuery(); deleteWrapper.eq(StglMember::getRelationId, club.getId()) .eq(StglMember::getMemberType, 1) // 社团成员 - .eq(StglMember::getRoleType, 2); // 副社长角色 + .eq(StglMember::getRoleType, "副社长"); // 副社长角色 memberMapper.delete(deleteWrapper); // 2. 处理单个副社长字段(向后兼容) @@ -851,7 +992,7 @@ public class StglClubServiceImpl implements IStglClubService { lqw.eq(StglMember::getMemberType, 1); // 社团成员 lqw.eq(StglMember::getRelationId, clubId); // 该社团 lqw.eq(StglMember::getUserId, userId); // 指定用户 - lqw.eq(StglMember::getRoleType, 1); // 社长角色 (1-社长) + lqw.eq(StglMember::getRoleType, "社长"); // 社长角色 - 修复:使用字符串而不是数值 lqw.eq(StglMember::getStatus, 2); // 已加入状态 (2-已加入) StglMember member = memberMapper.selectOne(lqw); @@ -897,7 +1038,7 @@ public class StglClubServiceImpl implements IStglClubService { LambdaQueryWrapper oldPresidentLqw = Wrappers.lambdaQuery(); oldPresidentLqw.eq(StglMember::getMemberType, 1); // 社团成员 oldPresidentLqw.eq(StglMember::getRelationId, clubId); - oldPresidentLqw.eq(StglMember::getRoleType, 1); // 社长 + oldPresidentLqw.eq(StglMember::getRoleType, "社长"); // 社长 oldPresidentLqw.eq(StglMember::getStatus, 2); // 已加入状态 StglMember oldPresidentMember = memberMapper.selectOne(oldPresidentLqw); @@ -936,7 +1077,7 @@ public class StglClubServiceImpl implements IStglClubService { // 如果新社长已经是成员,更新角色和状态 StglMember updateNewPresident = new StglMember(); updateNewPresident.setId(newPresidentMember.getId()); - updateNewPresident.setRoleType(1); // 社长 + updateNewPresident.setRoleType("社长"); // 社长 updateNewPresident.setStatus(2); // 已加入状态 updateNewPresident.setJoinTime(new Date()); memberMapper.updateById(updateNewPresident); @@ -948,7 +1089,7 @@ public class StglClubServiceImpl implements IStglClubService { newMember.setUserId(newPresidentUserId); newMember.setStudentNo(newPresidentStudent.getStudentNo()); newMember.setStudentName(newPresidentStudent.getName()); - newMember.setRoleType(1); // 社长 + newMember.setRoleType("社长"); // 社长 newMember.setJoinTime(new Date()); newMember.setStatus(2); // 已加入状态 memberMapper.insert(newMember); @@ -957,4 +1098,114 @@ public class StglClubServiceImpl implements IStglClubService { return true; } + /** + * 为指导老师分配角色 + * + * @param club 社团信息 + */ + private void assignAdvisorRoles(StglClub club) { + try { + List advisorUserIds = extractAdvisorUserIds(club); + if (!advisorUserIds.isEmpty()) { + advisorRoleAssigner.assignAdvisorRole(advisorUserIds); + log.info("成功为社团 {} 的指导老师分配角色,指导老师数量: {}", club.getClubName(), advisorUserIds.size()); + } + } catch (Exception e) { + log.error("为社团 {} 的指导老师分配角色时发生异常", club.getClubName(), e); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 处理指导老师角色分配(更新时使用) + * + * @param oldClub 更新前的社团信息 + * @param newClub 更新后的社团信息 + */ + private void handleAdvisorRoleAssignment(StglClub oldClub, StglClub newClub) { + try { + // 获取更新前后的指导老师用户ID列表 + List oldAdvisorUserIds = oldClub != null ? extractAdvisorUserIds(oldClub) : new ArrayList<>(); + List newAdvisorUserIds = extractAdvisorUserIds(newClub); + + // 找出新增的指导老师 + List addedAdvisorUserIds = newAdvisorUserIds.stream() + .filter(id -> !oldAdvisorUserIds.contains(id)) + .collect(Collectors.toList()); + + // 找出移除的指导老师 + List removedAdvisorUserIds = oldAdvisorUserIds.stream() + .filter(id -> !newAdvisorUserIds.contains(id)) + .collect(Collectors.toList()); + + // 为新指导老师分配角色 + if (!addedAdvisorUserIds.isEmpty()) { + advisorRoleAssigner.assignAdvisorRole(addedAdvisorUserIds); + log.info("社团 {} 新增指导老师,成功分配角色,数量: {}", newClub.getClubName(), addedAdvisorUserIds.size()); + } + + // 移除旧指导老师的角色 + if (!removedAdvisorUserIds.isEmpty()) { + advisorRoleAssigner.removeAdvisorRoles(removedAdvisorUserIds); + log.info("社团 {} 移除指导老师,成功移除角色,数量: {}", newClub.getClubName(), removedAdvisorUserIds.size()); + } + } catch (Exception e) { + log.error("处理社团 {} 的指导老师角色分配时发生异常", newClub.getClubName(), e); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 从社团信息中提取指导老师用户ID列表 + * + * @param club 社团信息 + * @return 指导老师用户ID列表 + */ + private List extractAdvisorUserIds(StglClub club) { + List advisorUserIds = new ArrayList<>(); + + try { + // 优先从JSON字段读取指导老师数据 + if (StringUtils.isNotBlank(club.getAdvisorsJson())) { + List> advisors = JsonUtils.parseObject(club.getAdvisorsJson(), new TypeReference>>() {}); + for (Map advisor : advisors) { + // 修复:支持嵌套的JSON结构,从teacher子对象中提取userId + Object userIdObj = null; + + // 尝试直接从advisor对象获取userId(兼容旧格式) + if (advisor.containsKey("userId")) { + userIdObj = advisor.get("userId"); + } + // 尝试从teacher子对象获取userId(新格式) + else if (advisor.containsKey("teacher")) { + Object teacherObj = advisor.get("teacher"); + if (teacherObj instanceof Map) { + @SuppressWarnings("unchecked") + Map teacher = (Map) teacherObj; + userIdObj = teacher.get("userId"); + } + } + + if (userIdObj != null) { + Long userId = Long.valueOf(userIdObj.toString()); + if (userId != null) { + advisorUserIds.add(userId); + } + } + } + } + + // 如果没有JSON数据,尝试从单一字段获取 + if (advisorUserIds.isEmpty() && StringUtils.isNotBlank(club.getAdvisorName())) { + // 这里需要根据指导老师姓名查找用户ID,暂时跳过 + // 因为单一字段模式下没有用户ID信息 + log.debug("社团 {} 使用单一指导老师字段,无法获取用户ID", club.getClubName()); + } + } catch (Exception e) { + log.error("解析社团 {} 的指导老师数据时发生异常", club.getClubName(), e); + } + + return advisorUserIds; + } + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglMemberServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglMemberServiceImpl.java index b0594731..3ef76506 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglMemberServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglMemberServiceImpl.java @@ -85,7 +85,8 @@ public class StglMemberServiceImpl implements IStglMemberService { bo.getStatus(), bo.getClubName(), bo.getTeamName(), - bo.getUserId() + bo.getUserId(), + bo.getParams() ); log.info("查询结果: total={}", allMembers.size()); @@ -131,7 +132,8 @@ public class StglMemberServiceImpl implements IStglMemberService { bo.getStatus(), bo.getClubName(), bo.getTeamName(), - bo.getUserId() + bo.getUserId(), + bo.getParams() ); } @@ -144,7 +146,35 @@ public class StglMemberServiceImpl implements IStglMemberService { lqw.like(StringUtils.isNotBlank(bo.getStudentNo()), StglMember::getStudentNo, bo.getStudentNo()); lqw.like(StringUtils.isNotBlank(bo.getStudentName()), StglMember::getStudentName, bo.getStudentName()); lqw.eq(bo.getRoleType() != null, StglMember::getRoleType, bo.getRoleType()); - lqw.eq(bo.getStatus() != null, StglMember::getStatus, bo.getStatus()); + + // 处理状态查询:优先使用statusList多状态查询,如果没有则使用单个status + if (params != null && params.get("statusList") != null) { + Object statusList = params.get("statusList"); + if (statusList instanceof List) { + List statuses = (List) statusList; + if (!statuses.isEmpty()) { + lqw.in(StglMember::getStatus, statuses); + } + } else if (statusList instanceof String) { + String statusStr = (String) statusList; + if (statusStr.contains(",")) { + // 处理 "0,3" 格式的字符串 + String[] statuses = statusStr.split(","); + List statusList2 = new ArrayList<>(); + for (String status : statuses) { + statusList2.add(status.trim()); + } + lqw.in(StglMember::getStatus, statusList2); + } else { + // 单个状态值 + lqw.eq(StglMember::getStatus, statusStr); + } + } + } else if (bo.getStatus() != null) { + // 如果没有statusList,则使用单个status字段 + lqw.eq(StglMember::getStatus, bo.getStatus()); + } + lqw.between(params.get("beginJoinTime") != null && params.get("endJoinTime") != null, StglMember::getJoinTime, params.get("beginJoinTime"), params.get("endJoinTime")); lqw.orderByDesc(StglMember::getJoinTime); @@ -208,7 +238,7 @@ public class StglMemberServiceImpl implements IStglMemberService { entity.setStatus(2); // 默认为已加入状态(stgl_member_status字典) } if (entity.getRoleType() == null) { - entity.setRoleType(3); // 默认为普通成员 + entity.setRoleType("3"); // 默认为普通成员 } } @@ -289,7 +319,7 @@ public class StglMemberServiceImpl implements IStglMemberService { member.setMemberType(memberType); member.setRelationId(relationId); member.setUserId(userId); - member.setRoleType(roleType != null ? roleType : 3); + member.setRoleType(roleType != null ? roleType.toString() : "3"); member.setJoinTime(now); member.setStatus(2); // 已加入状态(stgl_member_status字典) return member; @@ -309,7 +339,7 @@ public class StglMemberServiceImpl implements IStglMemberService { public Boolean updateMemberRole(Long id, Integer roleType) { StglMember member = new StglMember(); member.setId(id); - member.setRoleType(roleType); + member.setRoleType(roleType.toString()); return baseMapper.updateById(member) > 0; } @@ -395,8 +425,8 @@ public class StglMemberServiceImpl implements IStglMemberService { memberBo.setStudentNo(memberVo.getStudentNo()); memberBo.setStudentName(memberVo.getStudentName()); memberBo.setRelationId(memberVo.getRelationId()); - memberBo.setRoleType(memberVo.getRoleType() != null ? memberVo.getRoleType() : 1); // 默认普通成员 - memberBo.setStatus(memberVo.getStatus() != null ? memberVo.getStatus() : 1); // 默认正常状态 + memberBo.setRoleType(memberVo.getRoleType() != null ? memberVo.getRoleType() : "1"); // 默认普通成员 + memberBo.setStatus(memberVo.getStatus() != null ? memberVo.getStatus() : "1"); // 默认正常状态 memberBo.setJoinTime(memberVo.getJoinTime() != null ? memberVo.getJoinTime() : new Date()); // 检查是否已存在 @@ -469,16 +499,17 @@ public class StglMemberServiceImpl implements IStglMemberService { null, // status null, // clubName null, // teamName - bo.getUserId() + bo.getUserId(), + null // params ); // 基于权限过滤后的数据进行统计 long totalCount = allMembers.size(); long activeCount = allMembers.stream() - .mapToLong(member -> member.getStatus() != null && member.getStatus() == 2 ? 1 : 0) + .mapToLong(member -> member.getStatus() != null && "2".equals(member.getStatus()) ? 1 : 0) .sum(); long pendingCount = allMembers.stream() - .mapToLong(member -> member.getStatus() != null && member.getStatus() == 1 ? 1 : 0) + .mapToLong(member -> member.getStatus() != null && "1".equals(member.getStatus()) ? 1 : 0) .sum(); Map stats = new HashMap<>(); @@ -597,7 +628,7 @@ public class StglMemberServiceImpl implements IStglMemberService { // 查询用户作为队长的志愿者队伍 StglMemberBo captainBo = new StglMemberBo(); captainBo.setMemberType(2); // 志愿者成员 - captainBo.setRoleType(0); // 队长角色 + captainBo.setRoleType("0"); // 队长角色 List captainRecords = baseMapper.selectMemberWithUserInfo( captainBo.getMemberType(), @@ -608,7 +639,8 @@ public class StglMemberServiceImpl implements IStglMemberService { null, // status null, // clubName null, // teamName - userId // userId 权限过滤 + userId, // userId 权限过滤 + null // params ); return captainRecords.stream() diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglVolunteerTeamServiceImpl.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglVolunteerTeamServiceImpl.java index f252c67d..abe764c5 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglVolunteerTeamServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/service/impl/StglVolunteerTeamServiceImpl.java @@ -25,13 +25,16 @@ import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.SysUser; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.stgl.utils.AdvisorRoleAssigner; import cn.dev33.satoken.stp.StpUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import lombok.extern.slf4j.Slf4j; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.Objects; /** * 志愿者队伍Service业务层处理 @@ -39,6 +42,7 @@ import java.util.List; * @author Cursor AI * @date 2025-01-07 */ +@Slf4j @RequiredArgsConstructor @Service public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { @@ -47,6 +51,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { private final StglMemberMapper memberMapper; private final XgStudentMsgMapper studentMsgMapper; private final SysUserMapper userMapper; + private final AdvisorRoleAssigner advisorRoleAssigner; /** * 查询志愿者队伍 @@ -148,6 +153,8 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { bo.setId(add.getId()); // 自动创建队长的成员记录 createLeaderMemberRecord(add); + // 为指导老师分配角色 + assignAdvisorRole(add); } return flag; } @@ -161,12 +168,20 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { StglVolunteerTeam update = MapstructUtils.convert(bo, StglVolunteerTeam.class); validEntityBeforeSave(update); + // 获取更新前的队伍信息,用于比较指导老师变化 + StglVolunteerTeam oldTeam = null; + if (update.getId() != null) { + oldTeam = baseMapper.selectById(update.getId()); + } + // 更新队伍基本信息 boolean updateResult = baseMapper.updateById(update) > 0; if (updateResult) { // 同步更新队长的成员记录 syncLeaderInMembers(update); + // 处理指导老师角色分配 + handleAdvisorRoleAssignment(oldTeam, update); } return updateResult; @@ -220,7 +235,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { leader.setUserId(team.getLeaderUserId()); leader.setStudentNo(team.getLeaderStudentNo()); leader.setStudentName(team.getLeaderName()); - leader.setRoleType(0); // 队长 (stgl_volunteer_role=0) + leader.setRoleType("队长"); // 队长角色 leader.setJoinTime(new Date()); leader.setStatus(2); // 已加入状态 leader.setRemark("志愿者队伍创建时自动添加"); @@ -256,7 +271,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { LambdaQueryWrapper deleteWrapper = Wrappers.lambdaQuery(); deleteWrapper.eq(StglMember::getRelationId, team.getId()) .eq(StglMember::getMemberType, 2) // 志愿者成员 - .eq(StglMember::getRoleType, 0); // 队长角色 + .eq(StglMember::getRoleType, "队长"); // 队长角色 memberMapper.delete(deleteWrapper); // 2. 创建新的队长成员记录 @@ -267,7 +282,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { leader.setUserId(team.getLeaderUserId()); leader.setStudentNo(team.getLeaderStudentNo()); leader.setStudentName(team.getLeaderName()); - leader.setRoleType(0); // 队长 (stgl_volunteer_role=0) + leader.setRoleType("队长"); // 队长角色 leader.setJoinTime(new Date()); leader.setStatus(2); // 已加入状态 leader.setRemark("志愿者队伍修改时同步更新"); @@ -303,7 +318,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { query.eq(StglMember::getMemberType, 2); // 志愿者成员 query.eq(StglMember::getRelationId, teamId); // 指定队伍 query.eq(StglMember::getStudentNo, studentNo); // 指定学号 - query.eq(StglMember::getRoleType, 0); // 队长角色 + query.eq(StglMember::getRoleType, "0"); // 队长角色 query.eq(StglMember::getStatus, 2); // 已加入状态 return memberMapper.selectCount(query) > 0; @@ -433,7 +448,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { member.setUserId(LoginHelper.getUserId()); // 设置当前登录用户ID member.setStudentName(applicationBo.getStudentName()); member.setStudentNo(applicationBo.getStudentNo()); - member.setRoleType(1); // 1-队员(志愿者角色) + member.setRoleType("1"); // 1-队员(志愿者角色) member.setStatus(0); // 0-待审核 member.setJoinTime(new Date()); @@ -540,7 +555,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { leader.setUserId(team.getLeaderUserId()); leader.setStudentNo(team.getLeaderStudentNo()); leader.setStudentName(team.getLeaderName()); - leader.setRoleType(0); // 队长 (stgl_volunteer_role=0) + leader.setRoleType("0"); // 队长 (stgl_volunteer_role=0) leader.setJoinTime(team.getCreateTime() != null ? team.getCreateTime() : new Date()); leader.setStatus(2); // 已加入状态 leader.setRemark("补充缺失的队长成员记录"); @@ -657,7 +672,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { // 如果新队长已经是成员,更新角色和状态 StglMember updateNewLeader = new StglMember(); updateNewLeader.setId(newLeaderMember.getId()); - updateNewLeader.setRoleType(0); // 队长角色 + updateNewLeader.setRoleType("0"); // 队长角色 updateNewLeader.setStatus(2); // 已加入状态 updateNewLeader.setJoinTime(new Date()); updateNewLeader.setUpdateBy(LoginHelper.getUserId()); @@ -675,7 +690,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { newMember.setUserId(newLeaderUserId); newMember.setStudentNo(newLeaderStudent.getStudentNo()); newMember.setStudentName(newLeaderStudent.getName()); - newMember.setRoleType(0); // 队长角色 + newMember.setRoleType("0"); // 队长角色 newMember.setJoinTime(new Date()); newMember.setStatus(2); // 已加入状态 newMember.setCreateBy(LoginHelper.getUserId()); @@ -816,4 +831,92 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { List members = memberMapper.selectList(wrapper); return members.isEmpty() ? null : members.get(0); } + + /** + * 修改志愿者团队报名开启状态 + * + * @param id 团队ID + * @param sighOpen 报名开启状态(Y/N) + * @return 是否操作成功 + */ + @Override + public Boolean changeSighOpenStatus(Long id, String sighOpen) { + StglVolunteerTeam team = new StglVolunteerTeam(); + team.setId(id); + team.setSighOpen(sighOpen); + return baseMapper.updateById(team) > 0; + } + + /** + * 为指导老师分配角色 + * + * @param team 志愿者队伍信息 + */ + private void assignAdvisorRole(StglVolunteerTeam team) { + try { + Long advisorUserId = extractAdvisorUserId(team); + if (advisorUserId != null) { + advisorRoleAssigner.assignAdvisorRole(advisorUserId); + log.info("成功为志愿者队伍 {} 的指导老师分配角色,指导老师用户ID: {}", team.getTeamName(), advisorUserId); + } + } catch (Exception e) { + log.error("为志愿者队伍 {} 的指导老师分配角色时发生异常", team.getTeamName(), e); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 处理指导老师角色分配(更新时使用) + * + * @param oldTeam 更新前的队伍信息 + * @param newTeam 更新后的队伍信息 + */ + private void handleAdvisorRoleAssignment(StglVolunteerTeam oldTeam, StglVolunteerTeam newTeam) { + try { + // 获取更新前后的指导老师用户ID + Long oldAdvisorUserId = oldTeam != null ? extractAdvisorUserId(oldTeam) : null; + Long newAdvisorUserId = extractAdvisorUserId(newTeam); + + // 如果指导老师发生变化 + if (!Objects.equals(oldAdvisorUserId, newAdvisorUserId)) { + // 移除旧指导老师的角色 + if (oldAdvisorUserId != null) { + advisorRoleAssigner.removeAdvisorRole(oldAdvisorUserId); + log.info("志愿者队伍 {} 移除指导老师,成功移除角色,用户ID: {}", newTeam.getTeamName(), oldAdvisorUserId); + } + + // 为新指导老师分配角色 + if (newAdvisorUserId != null) { + advisorRoleAssigner.assignAdvisorRole(newAdvisorUserId); + log.info("志愿者队伍 {} 新增指导老师,成功分配角色,用户ID: {}", newTeam.getTeamName(), newAdvisorUserId); + } + } + } catch (Exception e) { + log.error("处理志愿者队伍 {} 的指导老师角色分配时发生异常", newTeam.getTeamName(), e); + // 不抛出异常,避免影响主业务流程 + } + } + + /** + * 从志愿者队伍信息中提取指导老师用户ID + * + * @param team 志愿者队伍信息 + * @return 指导老师用户ID + */ + private Long extractAdvisorUserId(StglVolunteerTeam team) { + // 志愿者队伍目前使用单一指导老师字段,需要根据指导老师姓名查找用户ID + if (StringUtils.isNotBlank(team.getAdvisorName())) { + try { + // 这里需要根据指导老师姓名查找用户ID + // 由于志愿者队伍表没有直接存储指导老师用户ID,需要额外的查询逻辑 + // 暂时返回null,后续可以根据需要实现 + log.debug("志愿者队伍 {} 的指导老师 {} 需要根据姓名查找用户ID", team.getTeamName(), team.getAdvisorName()); + return null; + } catch (Exception e) { + log.error("查找志愿者队伍 {} 指导老师用户ID时发生异常", team.getTeamName(), e); + } + } + return null; + } + } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglClubMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglClubMapper.xml index f242cf17..0de5ec19 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglClubMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglClubMapper.xml @@ -39,6 +39,7 @@ + @@ -56,7 +57,7 @@ c.advisor_name, c.advisor_dept, c.advisor_phone, c.advisor_email, c.advisors_json, c.member_limit, c.departments, c.recruit_cycle, c.recruit_time, c.activity_frequency, c.funding_sources, - c.charter_url, c.status, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, c.tenant_id, c.deleted, + c.charter_url, c.status, c.sigh_open, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, c.tenant_id, c.deleted, COALESCE(m.member_count, 0) as memberCount from stgl_club c LEFT JOIN ( @@ -76,7 +77,7 @@ c.vice_president_name, c.vice_president_student_no, c.vice_president_dept, c.vice_president_major, c.vice_president_class, c.vice_president_phone, c.advisor_name, c.advisor_dept, c.advisor_phone, c.advisor_email, c.member_limit, c.departments, c.recruit_cycle, c.recruit_time, - c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.remark, + c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.sigh_open, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, COALESCE(m.member_count, 0) as memberCount FROM stgl_club c @@ -98,7 +99,7 @@ c.vice_president_name, c.vice_president_student_no, c.vice_president_dept, c.vice_president_major, c.vice_president_class, c.vice_president_phone, c.advisor_name, c.advisor_dept, c.advisor_phone, c.advisor_email, c.member_limit, c.departments, c.recruit_cycle, c.recruit_time, - c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.remark, + c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.sigh_open, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, COALESCE(m.member_count, 0) as memberCount FROM stgl_club c @@ -129,7 +130,7 @@ c.advisor_name, c.advisor_dept, c.advisor_phone, c.advisor_email, c.advisors_json, c.member_limit, c.departments, c.recruit_cycle, c.recruit_time, - c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.remark, + c.activity_frequency, c.funding_sources, c.charter_url, c.status, c.sigh_open, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, COALESCE(m.member_count, 0) as memberCount FROM stgl_club c diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMemberMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMemberMapper.xml index a3e84657..9c625935 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMemberMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMemberMapper.xml @@ -160,7 +160,35 @@ AND m.role_type = #{roleType} - + + + + + + AND m.status IN + + #{status} + + + + + + + + AND m.status IN + + #{status} + + + + AND m.status = #{params.statusList} + + + + + + + AND m.status = #{status} diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMyMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMyMapper.xml index 3b5b2849..557e0707 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMyMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/StglMyMapper.xml @@ -99,13 +99,28 @@ END as organization_name, a.instructors, CAST(a.activity_status AS CHAR) as activity_status, - -- 动态计算报名状态:基于当前时间和报名时间范围 + -- 动态计算报名状态:优先根据活动状态,再根据报名时间范围 CAST( CASE - WHEN a.registration_start IS NULL OR a.registration_end IS NULL THEN a.registration_status - WHEN NOW() < a.registration_start THEN '0' - WHEN NOW() >= a.registration_start AND NOW() <= a.registration_end THEN '1' - WHEN NOW() > a.registration_end THEN '2' + -- 首先根据活动状态强制设置(优先级最高) + WHEN a.activity_status = '0' THEN '0' -- 草稿 → 未开始(固定) + WHEN a.activity_status = '1' THEN '0' -- 未开始 → 未开始(固定) + WHEN a.activity_status = '2' THEN '0' -- 待审批 → 未开始(固定) + WHEN a.activity_status = '5' THEN '2' -- 已结束 → 报名结束(固定) + WHEN a.activity_status = '6' THEN '3' -- 已取消 → 已关闭(固定) + WHEN a.activity_status = '7' THEN '0' -- 已驳回 → 未开始(固定) + + -- 然后根据活动状态和报名时间判断 + WHEN a.activity_status = '3' OR a.activity_status = '4' THEN + CASE + WHEN a.registration_start IS NULL OR a.registration_end IS NULL THEN a.registration_status + + = a.registration_start AND NOW() <= a.registration_end THEN '1']]> + a.registration_end THEN '2']]> + ELSE a.registration_status + END + + -- 其他情况保持原状态 ELSE a.registration_status END AS CHAR ) as registration_status, diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityAttendanceMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityAttendanceMapper.xml index e0f17688..99d17fc5 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityAttendanceMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityAttendanceMapper.xml @@ -130,13 +130,7 @@ AND sar.user_id = #{userId} AND sar.approval_status = 1 -- 报名成功(审核通过) AND sa.activity_status = '4' -- 进行中 - -- 排除已有签到记录的活动 - AND NOT EXISTS ( - SELECT 1 FROM stgl_activity_sign sas2 - WHERE sas2.activity_id = sa.id - AND sas2.user_id = #{userId} - AND sas2.deleted = 0 - ) + -- 移除NOT EXISTS子查询,允许用户重复签到 ORDER BY sa.start_time ASC @@ -152,6 +146,18 @@ + + +