diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivity.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivity.java index 62f44acf..f3525a71 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivity.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/StglActivity.java @@ -186,6 +186,12 @@ public class StglActivity extends TenantEntity { @TableField("need_approval") private Integer needApproval; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + @TableField("activity_range") + private Integer activityRange; + /** * 活动状态 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglActivityBo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglActivityBo.java index c1db42fd..4273c1a2 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglActivityBo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/bo/StglActivityBo.java @@ -164,6 +164,11 @@ public class StglActivityBo extends BaseEntity { */ private Integer needApproval; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + private Integer activityRange; + /** * 活动状态 */ diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglActivityVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglActivityVo.java index f34cf05d..dacf563c 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglActivityVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglActivityVo.java @@ -208,24 +208,31 @@ public class StglActivityVo implements Serializable { @ExcelDictFormat(dictType = "sys_yes_no") private Integer needApproval; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + @ExcelProperty(value = "活动面向群体", converter = ExcelDictConvert.class, index = 23) + @ExcelDictFormat(dictType = "stgl_activity_range") + private Integer activityRange; + /** * 活动状态 */ - @ExcelProperty(value = "活动状态", converter = ExcelDictConvert.class, index = 23) + @ExcelProperty(value = "活动状态", converter = ExcelDictConvert.class, index = 24) @ExcelDictFormat(dictType = "stgl_activity_status") private String activityStatus; /** * 是否为已办活动 */ - @ExcelProperty(value = "是否为已办活动", converter = ExcelDictConvert.class, index = 29) + @ExcelProperty(value = "是否为已办活动", converter = ExcelDictConvert.class, index = 30) @ExcelDictFormat(dictType = "sys_yes_no") private Integer isFinished; /** * 活动总结报告 */ - @ExcelProperty(value = "活动总结报告", index = 27) + @ExcelProperty(value = "活动总结报告", index = 28) private String summary; /** @@ -236,7 +243,7 @@ public class StglActivityVo implements Serializable { /** * 活动成果 */ - @ExcelProperty(value = "活动成果", index = 28) + @ExcelProperty(value = "活动成果", index = 29) private String achievements; /** @@ -247,19 +254,19 @@ public class StglActivityVo implements Serializable { /** * 创建者姓名(关联查询) */ - @ExcelProperty(value = "创建者", index = 24) + @ExcelProperty(value = "创建者", index = 25) private String createByName; /** * 导入来源信息 */ - @ExcelProperty(value = "导入来源信息", index = 30) + @ExcelProperty(value = "导入来源信息", index = 31) private String importSource; /** * 备注 */ - @ExcelProperty(value = "备注", index = 31) + @ExcelProperty(value = "备注", index = 32) private String remark; /** @@ -287,13 +294,13 @@ public class StglActivityVo implements Serializable { /** * 报名人数统计(关联查询) */ - @ExcelProperty(value = "报名人数", index = 25) + @ExcelProperty(value = "报名人数", index = 26) private Integer registrationCount; /** * 平均评分(关联查询) */ - @ExcelProperty(value = "平均评分", index = 26) + @ExcelProperty(value = "平均评分", index = 27) private Double averageRating; } \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClassVo.java b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClassVo.java index 4ee0a398..75788a93 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClassVo.java +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/java/org/dromara/stgl/domain/vo/StglClassVo.java @@ -92,11 +92,6 @@ public class StglClassVo implements Serializable { */ private String tenantId; - /** - * 版本号 - */ - private Long version; - /** * 逻辑删除 */ 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 01cf1ee3..87c62335 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 @@ -116,7 +116,7 @@ public class StglClubRegisterVo implements Serializable { /** * 我在该社团的角色类型(用户相关查询时使用) */ - private Integer myRoleType; + private String myRoleType; /** * 我加入该社团的时间(用户相关查询时使用) 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 40650f20..98ba7797 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 @@ -268,7 +268,7 @@ public class StglClubVo implements Serializable { /** * 我在该社团的角色类型(用户相关查询时使用) */ - private Integer myRoleType; + private String roleType; /** * 我加入该社团的时间(用户相关查询时使用) 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 d212a4d5..69e16c7c 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 @@ -217,6 +217,22 @@ public class StglVolunteerTeamVo implements Serializable { */ private Boolean hasJoined; + /** + * 我在该队伍的角色类型(用户相关查询时使用) + */ + private String roleType; + + /** + * 我加入该队伍的时间(用户相关查询时使用) + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date myJoinTime; + + /** + * 我在该队伍的角色名称(用户相关查询时使用) + */ + private String myRoleName; + /** * 队伍简介(用于前端显示description字段) */ 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 7deb36ce..2670434b 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 @@ -3,6 +3,7 @@ package org.dromara.stgl.mapper; import org.dromara.stgl.domain.StglMember; import org.dromara.stgl.domain.vo.StglMemberVo; import org.dromara.stgl.domain.vo.StglClubVo; +import org.dromara.stgl.domain.vo.StglVolunteerTeamVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.apache.ibatis.annotations.Param; @@ -86,4 +87,12 @@ public interface StglMemberMapper extends BaseMapperPlus selectClubAdmins(@Param("clubId") Long clubId); + /** + * 查询用户参与的志愿者队伍列表 + * + * @param userId 用户ID + * @return 志愿者队伍列表 + */ + List selectUserVolunteerTeams(@Param("userId") Long userId); + } \ 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 62057bf5..a49dd247 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 @@ -22,6 +22,7 @@ import org.dromara.stgl.domain.vo.StglActivityVo; import org.dromara.stgl.domain.vo.ActivityRatingVo; import org.dromara.stgl.mapper.StglActivityMapper; import org.dromara.stgl.mapper.StglActivityRatingMapper; +import org.dromara.stgl.mapper.StglMemberMapper; import org.dromara.stgl.service.IStglActivityService; import org.dromara.stgl.utils.AdvisorRoleAssigner; import org.springframework.stereotype.Service; @@ -42,6 +43,8 @@ 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.domain.vo.StglClubVo; +import org.dromara.stgl.domain.vo.StglVolunteerTeamVo; import org.dromara.stgl.mapper.StglClubMapper; import org.dromara.stgl.mapper.StglVolunteerTeamMapper; import org.dromara.system.domain.SysUser; @@ -64,6 +67,7 @@ public class StglActivityServiceImpl extends ServiceImpl params = new HashMap<>(); params.put("registrationStatusList", Arrays.asList("0", "1")); + + // 获取当前用户ID + Long currentUserId = LoginHelper.getUserId(); + + // 查询用户所属的社团和志愿者队伍,用于过滤activity_range=1的活动 + List userClubs = stglMemberMapper.selectUserClubs(currentUserId); + List userTeams = stglMemberMapper.selectUserVolunteerTeams(currentUserId); + + // 构建用户组织权限列表 + List userOrganizations = new ArrayList<>(); + + // 添加用户所属的社团(格式:1-社团ID) + for (StglClubVo club : userClubs) { + userOrganizations.add("1-" + club.getId()); + } + + // 添加用户所属的志愿者队伍(格式:2-队伍ID) + for (StglVolunteerTeamVo team : userTeams) { + userOrganizations.add("2-" + team.getId()); + } + + // 将用户组织权限列表传递给查询条件 + params.put("userOrganizations", userOrganizations); + params.put("currentUserId", currentUserId); + activity.setParams(params); // 使用XML中定义的复杂查询方法,包含关联查询获取related_club_name等字段 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 9fce9b6a..9ac49df7 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 @@ -245,7 +245,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { member.setUserId(userId); member.setStudentNo(studentNo); member.setStudentName(studentName != null ? studentName : user.getNickName()); // 如果没有学生信息,使用用户昵称 - member.setRoleType("4"); // 普通成员 + // 申请时不设置roleType,等待审核通过后再设置 member.setJoinTime(new Date()); member.setStatus(0); // 待审核状态(stgl_member_status字典,新报名需审核) member.setRemark(reason); // 将申请理由存储到备注字段 @@ -337,7 +337,7 @@ public class StglClubRegisterServiceImpl implements IStglClubRegisterService { vo.setRemark(clubVo.getRemark()); // 设置用户在社团中的角色信息 - vo.setMyRoleType(clubVo.getMyRoleType()); + vo.setMyRoleType(clubVo.getRoleType()); vo.setMyJoinTime(clubVo.getMyJoinTime()); vo.setMyRoleName(clubVo.getMyRoleName()); // 设置已加入状态 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 58078359..70ef2fac 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 @@ -1110,7 +1110,7 @@ public class StglClubServiceImpl implements IStglClubService { // 8.1 移除原社长的角色(根据社团信息获取原社长的用户ID) Long oldPresidentUserId = findUserIdByStudentNo(club.getPresidentStudentNo()); if (oldPresidentUserId != null) { - removePresidentRole(oldPresidentUserId); + removePresidentRole(oldPresidentUserId, club.getId()); log.info("社团转让:成功移除原社长角色,用户ID: {}, 社团: {}", oldPresidentUserId, club.getClubName()); } @@ -1295,8 +1295,21 @@ public class StglClubServiceImpl implements IStglClubService { * * @param presidentUserId 社长用户ID */ - private void removePresidentRole(Long presidentUserId) { + private void removePresidentRole(Long presidentUserId, Long excludeClubId) { try { + // 1. 获取用户担任社长的所有社团(排除当前转让的社团) + List userClubIds = getUserPresidentClubIds(presidentUserId); + if (excludeClubId != null) { + userClubIds.remove(excludeClubId); + } + + // 2. 如果还有其他社团,保留stgl_president角色 + if (!userClubIds.isEmpty()) { + log.info("用户 {} 还担任其他 {} 个社团的社长,保留stgl_president角色", presidentUserId, userClubIds.size()); + return; + } + + // 3. 这是最后一个社团,删除角色 int result = sysUserRoleMapper.delete( Wrappers.lambdaQuery() .eq(SysUserRole::getUserId, presidentUserId) @@ -1304,9 +1317,9 @@ public class StglClubServiceImpl implements IStglClubService { ); if (result > 0) { - log.info("成功移除用户 {} 的社长角色", presidentUserId); + log.info("用户 {} 不再担任任何社团社长,成功移除stgl_president角色", presidentUserId); } else { - log.debug("用户 {} 没有社长角色需要移除", presidentUserId); + log.debug("用户 {} 没有stgl_president角色需要移除", presidentUserId); } } catch (Exception e) { log.error("移除用户 {} 的社长角色时发生异常", presidentUserId, e); 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 1be2392c..2eaf8007 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 @@ -386,13 +386,20 @@ public class StglMemberServiceImpl implements IStglMemberService { throw new RuntimeException("该申请已审核过,无法重复审核"); } - // 更新成员状态 + // 更新成员状态和角色 StglMember updateMember = new StglMember(); updateMember.setId(id); if (approved) { updateMember.setStatus(2); // 已加入状态(stgl_member_status字典) + // 根据成员类型设置不同的角色 + if (member.getMemberType() == 1) { + updateMember.setRoleType("普通成员"); // 社团成员 + } else if (member.getMemberType() == 2) { + updateMember.setRoleType("队员"); // 志愿者队伍成员 + } } else { updateMember.setStatus(3); // 已驳回状态(stgl_member_status字典) + updateMember.setRoleType(null); // 拒绝时清空角色 } return baseMapper.updateById(updateMember) > 0; 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 70fe91c0..32503971 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 @@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional; import lombok.extern.slf4j.Slf4j; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Objects; @@ -451,6 +452,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { LambdaQueryWrapper memberLqw = Wrappers.lambdaQuery(); memberLqw.eq(StglMember::getMemberType, 2) // 2-志愿者 .eq(StglMember::getRelationId, applicationBo.getTeamId()) + .eq(StglMember::getUserId, LoginHelper.getUserId()) // 使用当前登录用户ID,避免查询到其他用户记录 .eq(StglMember::getStudentNo, applicationBo.getStudentNo()); StglMember existingMember = memberMapper.selectOne(memberLqw); if (existingMember != null) { @@ -470,7 +472,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { member.setUserId(LoginHelper.getUserId()); // 设置当前登录用户ID member.setStudentName(applicationBo.getStudentName()); member.setStudentNo(applicationBo.getStudentNo()); - member.setRoleType("队员"); // 队员角色 - 直接写入字符"队员" + // 申请时不设置roleType,等待审核通过后再设置 member.setStatus(0); // 0-待审核 member.setJoinTime(new Date()); @@ -662,7 +664,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { try { // 5.1 移除原队长的角色 if (oldLeaderUserId != null) { - removeLeaderRole(oldLeaderUserId); + removeLeaderRole(oldLeaderUserId, teamId); log.info("志愿者队伍转让:成功移除原队长角色,用户ID: {}, 队伍: {}", oldLeaderUserId, team.getTeamName()); } @@ -1000,7 +1002,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { if (!Objects.equals(oldLeaderUserId, newLeaderUserId)) { // 移除旧队长的角色 if (oldLeaderUserId != null) { - removeLeaderRole(oldLeaderUserId); + removeLeaderRole(oldLeaderUserId, newTeam.getId()); log.info("志愿者队伍 {} 更换队长,成功移除原队长角色,用户ID: {}", newTeam.getTeamName(), oldLeaderUserId); } @@ -1015,13 +1017,53 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { } } + /** + * 获取用户担任队长的所有志愿者队伍ID列表 + * + * @param userId 用户ID + * @return 队伍ID列表 + */ + private List getUserLeaderTeamIds(Long userId) { + if (userId == null) { + return Collections.emptyList(); + } + + try { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StglVolunteerTeam::getLeaderUserId, userId); + + List teams = baseMapper.selectList(lqw); + return teams.stream() + .map(StglVolunteerTeam::getId) + .distinct() + .collect(Collectors.toList()); + } catch (Exception e) { + log.error("查询用户担任队长的志愿者队伍失败: {}", e.getMessage(), e); + return Collections.emptyList(); + } + } + /** * 移除队长角色 * * @param leaderUserId 队长用户ID + * @param excludeTeamId 排除的队伍ID(当前转让的队伍) */ - private void removeLeaderRole(Long leaderUserId) { + private void removeLeaderRole(Long leaderUserId, Long excludeTeamId) { try { + // 1. 获取用户担任队长的所有队伍(排除当前转让的队伍) + List userTeamIds = getUserLeaderTeamIds(leaderUserId); + if (excludeTeamId != null) { + userTeamIds.remove(excludeTeamId); + } + + // 2. 如果还有其他队伍,保留stgl_volunteer_captain角色 + if (!userTeamIds.isEmpty()) { + log.info("用户 {} 还担任其他 {} 个志愿者队伍的队长,保留stgl_volunteer_captain角色", leaderUserId, userTeamIds.size()); + return; + } + + // 3. 这是最后一个队伍,删除角色 int result = sysUserRoleMapper.delete( Wrappers.lambdaQuery() .eq(SysUserRole::getUserId, leaderUserId) @@ -1029,9 +1071,9 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService { ); if (result > 0) { - log.info("成功移除用户 {} 的志愿者队长角色", leaderUserId); + log.info("用户 {} 不再担任任何志愿者队伍队长,成功移除stgl_volunteer_captain角色", leaderUserId); } else { - log.debug("用户 {} 没有志愿者队长角色需要移除", leaderUserId); + log.debug("用户 {} 没有stgl_volunteer_captain角色需要移除", leaderUserId); } } catch (Exception e) { log.error("移除用户 {} 的志愿者队长角色时发生异常", leaderUserId, e); 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 a8a9ee41..f94b620e 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 @@ -214,7 +214,7 @@ WHERE member_type = #{memberType} AND relation_id = #{relationId} AND user_id = #{userId} - AND status = 1 + AND status = 2 AND deleted = 0 @@ -228,19 +228,14 @@ 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, - m.role_type as myRoleType, + m.role_type, m.join_time as myJoinTime, - CASE m.role_type - WHEN 1 THEN '社长' - WHEN 2 THEN '副社长' - WHEN 3 THEN '部长' - ELSE '未知' - END as myRoleName + m.role_type as myRoleName FROM stgl_club c INNER JOIN stgl_member m ON c.id = m.relation_id WHERE m.user_id = #{userId} AND m.member_type = 1 - AND m.status = 1 + AND m.status = 2 AND m.deleted = 0 AND c.deleted = 0 ORDER BY m.role_type ASC, m.join_time DESC @@ -252,7 +247,7 @@ FROM stgl_member WHERE member_type = 1 AND relation_id = #{clubId} - AND status = 1 + AND status = 2 AND deleted = 0 @@ -273,9 +268,30 @@ WHERE m.member_type = 1 AND m.relation_id = #{clubId} AND m.role_type IN (1, 2) - AND m.status = 1 + AND m.status = 2 AND m.deleted = 0 ORDER BY m.role_type ASC + + + \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityMapper.xml index f7a23ce8..a4adce16 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglActivityMapper.xml @@ -32,6 +32,7 @@ + @@ -79,7 +80,7 @@ -- 其他情况保持原状态 ELSE sa.registration_status END AS registration_status, - sa.max_participants, sa.max_teams, sa.team_size_min, sa.team_size_max, sa.need_approval, + sa.max_participants, sa.max_teams, sa.team_size_min, sa.team_size_max, sa.need_approval, sa.activity_range, sa.activity_status, sa.is_finished, sa.summary, sa.summary_attachments, sa.achievements, sa.achievements_attachments, sa.import_source, sa.remark, sa.create_by, sa.create_time, sa.update_by, sa.update_time, -- 关联查询创建者姓名 @@ -282,6 +283,26 @@ AND sa.tenant_id = #{activity.tenantId} + + + AND ( + sa.activity_range = 0 + OR ( + sa.activity_range = 1 + + + AND CONCAT(sa.related_type, '-', sa.related_club_id) IN + + #{org} + + + + AND 1 = 0 + + + ) + ) + ${activity.params.dataScope} diff --git a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglClassMapper.xml b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglClassMapper.xml index 2311497a..ea22f2a6 100644 --- a/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglClassMapper.xml +++ b/backend/ruoyi-modules/ruoyi-stgl/src/main/resources/mapper/stgl/StglClassMapper.xml @@ -19,7 +19,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - @@ -58,7 +57,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" s.update_by, s.update_time, s.tenant_id, - s.version, s.deleted FROM xg_student_msg s LEFT JOIN xg_class_msg c ON s.class_id = c.id @@ -69,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" FROM stgl_member m WHERE m.member_type = 1 AND m.deleted = 0 - AND m.status = 1 + AND m.status = 2 GROUP BY m.user_id ) club_stats ON s.id = club_stats.user_id LEFT JOIN ( @@ -79,7 +77,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" FROM stgl_member m WHERE m.member_type = 2 AND m.deleted = 0 - AND m.status = 1 + AND m.status = 2 GROUP BY m.user_id ) volunteer_stats ON s.id = volunteer_stats.user_id LEFT JOIN ( @@ -150,9 +148,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" WHERE m.user_id = #{studentId} AND m.member_type = 1 AND m.deleted = 0 - AND m.status = 1 + AND m.status = 2 AND c.deleted = 0 - AND c.status = 1 ORDER BY c.create_time DESC @@ -175,7 +172,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" WHERE m.user_id = #{studentId} AND m.member_type = 2 AND m.deleted = 0 - AND m.status = 1 + AND m.status = 2 AND vt.deleted = 0 AND vt.status = 1 ORDER BY vt.create_time DESC @@ -189,6 +186,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" a.activity_type as activityType, a.activity_theme as activityTheme, a.location, + a.start_time, CONCAT( DATE_FORMAT(a.start_time, '%Y-%m-%d %H:%i'), ' 至 ', @@ -213,29 +211,65 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" WHEN a.related_type = 1 THEN c.advisor_phone WHEN a.related_type = 2 THEN vt.advisor_phone ELSE '无' - END as advisorPhone + END as advisorPhone, + -- 优化的报名类型获取逻辑:先获取个人报名类型,如果没有则获取团队报名类型 + CASE + WHEN ar.registration_type IS NOT NULL THEN + CASE ar.registration_type + WHEN 1 THEN '个人报名' + WHEN 2 THEN '团队报名' + ELSE '未知' + END + WHEN team_ar.registration_type IS NOT NULL THEN + CASE team_ar.registration_type + WHEN 1 THEN '个人报名' + WHEN 2 THEN '团队报名' + ELSE '未知' + END + ELSE '暂无' + END as registrationType, + -- 优化的成绩获取逻辑:先获取个人成绩,如果没有则获取团队成绩 + COALESCE( + ar.score, + team_ar.score, + '暂无' + ) as score FROM stgl_activity a - LEFT JOIN stgl_club c ON a.related_club_id = c.id AND a.related_type = 1 - LEFT JOIN stgl_volunteer_team vt ON a.related_club_id = vt.id AND a.related_type = 2 + LEFT JOIN stgl_club c ON a.related_club_id = c.id AND a.related_type = 1 AND c.tenant_id = '000000' + LEFT JOIN stgl_volunteer_team vt ON a.related_club_id = vt.id AND a.related_type = 2 AND vt.tenant_id = '000000' + -- 个人报名记录关联 + LEFT JOIN stgl_activity_registration ar ON ar.activity_id = a.id AND ar.user_id = #{studentId} AND ar.deleted = 0 AND ar.tenant_id = '000000' + -- 团队报名记录关联:通过team_info获取队长的成绩 + LEFT JOIN stgl_activity_team_info ati ON ati.activity_id = a.id + AND ati.deleted = 0 + AND JSON_CONTAINS(ati.team_members, JSON_OBJECT('userId', CAST(#{studentId} AS CHAR))) + AND ati.tenant_id = '000000' + LEFT JOIN stgl_activity_registration team_ar ON team_ar.team_id = ati.id + AND team_ar.deleted = 0 + AND team_ar.tenant_id = '000000' + AND team_ar.registration_type = 2 WHERE a.deleted = 0 AND ( -- 个人报名 EXISTS ( - SELECT 1 FROM stgl_activity_registration ar - WHERE ar.activity_id = a.id - AND ar.user_id = #{studentId} - AND ar.deleted = 0 - AND ar.approval_status = 1 + SELECT 1 FROM stgl_activity_registration ar2 + WHERE ar2.activity_id = a.id + AND ar2.user_id = #{studentId} + AND ar2.deleted = 0 + AND ar2.approval_status = 1 + AND ar2.tenant_id = '000000' ) OR -- 团队报名(通过团队信息中的成员) EXISTS ( - SELECT 1 FROM stgl_activity_team_info ati - WHERE ati.activity_id = a.id - AND ati.deleted = 0 - AND JSON_CONTAINS(ati.team_members, JSON_OBJECT('userId', CAST(#{studentId} AS CHAR)), '$[*]') + SELECT 1 FROM stgl_activity_team_info ati2 + WHERE ati2.activity_id = a.id + AND ati2.deleted = 0 + AND JSON_CONTAINS(ati2.team_members, JSON_OBJECT('userId', CAST(#{studentId} AS CHAR))) + AND ati2.tenant_id = '000000' ) ) + AND a.tenant_id = '000000' ORDER BY a.start_time DESC diff --git a/web/src/api/stgl/activity/types.ts b/web/src/api/stgl/activity/types.ts index 0aba8f9c..aa502267 100644 --- a/web/src/api/stgl/activity/types.ts +++ b/web/src/api/stgl/activity/types.ts @@ -139,6 +139,11 @@ export interface StglActivityVO { */ needApproval?: number; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + activityRange?: number; + /** * 活动状态 */ @@ -366,6 +371,11 @@ export interface StglActivityForm { */ needApproval?: number; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + activityRange?: number; + /** * 活动状态 */ diff --git a/web/src/api/stgl/activityregisterhall/types.ts b/web/src/api/stgl/activityregisterhall/types.ts index e8935f0e..a4acf966 100644 --- a/web/src/api/stgl/activityregisterhall/types.ts +++ b/web/src/api/stgl/activityregisterhall/types.ts @@ -135,6 +135,11 @@ export interface StglActivityVo { */ needApproval: number; + /** + * 活动面向群体(0-无限制 1-本组织成员) + */ + activityRange: number; + /** * 活动状态 */ diff --git a/web/src/api/stgl/stclass/types.ts b/web/src/api/stgl/stclass/types.ts index 56633584..b075ad4a 100644 --- a/web/src/api/stgl/stclass/types.ts +++ b/web/src/api/stgl/stclass/types.ts @@ -259,6 +259,16 @@ export interface ActivityDetailVO { * 指导老师电话 */ advisorPhone: string; + + /** + * 报名类型 + */ + registrationType: string; + + /** + * 取得成绩 + */ + score: string; } /** diff --git a/web/src/views/stgl/activity/components/ActivityDetailView.vue b/web/src/views/stgl/activity/components/ActivityDetailView.vue index c9bf4a0a..22a247c9 100644 --- a/web/src/views/stgl/activity/components/ActivityDetailView.vue +++ b/web/src/views/stgl/activity/components/ActivityDetailView.vue @@ -212,6 +212,17 @@ + + +
+ +
+ +
+
+
+
+
@@ -362,8 +373,8 @@ interface Props { const props = defineProps(); const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const { stgl_activity_type, stgl_activity_status, stgl_registration_type, stgl_registration_status, sys_yes_no } = toRefs( - proxy?.useDict('stgl_activity_type', 'stgl_activity_status', 'stgl_registration_type', 'stgl_registration_status', 'sys_yes_no') +const { stgl_activity_type, stgl_activity_status, stgl_registration_type, stgl_registration_status, stgl_activity_range, sys_yes_no } = toRefs( + proxy?.useDict('stgl_activity_type', 'stgl_activity_status', 'stgl_registration_type', 'stgl_registration_status', 'stgl_activity_range', 'sys_yes_no') ); @@ -471,11 +482,13 @@ const downloadAttachment = (file: any) => { } }; -// 监听props变化,重新加载附件信息 +// 监听props变化,重新加载附件信息并重置activeTab watch( () => props.activity, (newActivity) => { if (newActivity && newActivity.id) { + // 重置为基本信息标签页,避免显示上次查看的标签页 + activeTab.value = 'basic'; loadAttachments(); } }, diff --git a/web/src/views/stgl/activity/components/ActivityRegistrationView.vue b/web/src/views/stgl/activity/components/ActivityRegistrationView.vue index a0e50722..b458825b 100644 --- a/web/src/views/stgl/activity/components/ActivityRegistrationView.vue +++ b/web/src/views/stgl/activity/components/ActivityRegistrationView.vue @@ -324,7 +324,7 @@ diff --git a/web/src/views/stgl/activity/components/RegisteredMembersTab.vue b/web/src/views/stgl/activity/components/RegisteredMembersTab.vue index 4ec6ef37..11fdd1c9 100644 --- a/web/src/views/stgl/activity/components/RegisteredMembersTab.vue +++ b/web/src/views/stgl/activity/components/RegisteredMembersTab.vue @@ -85,12 +85,12 @@ {{ parseTime(scope.row.registrationTime, '{y}-{m}-{d}') }} - + - + + + + + + + {{ scoreForm.registrationType === '2' ? scoreForm.teamName : scoreForm.studentName }} + + + {{ props.activityName }} + + + + + + + + (); const memberFormRef = ref(); +const scoreFormRef = ref(); const dialog = reactive({ visible: false, @@ -368,6 +406,11 @@ const viewDialog = reactive({ title: '' }); +const scoreDialog = reactive({ + visible: false, + title: '' +}); + const viewForm = reactive({ id: undefined, activityId: undefined, @@ -402,6 +445,21 @@ const teamInfo = ref(null); const teamMembers = ref([]); const loadingTeamInfo = ref(false); +// 成绩录入相关数据 +const scoreButtonLoading = ref(false); +const scoreForm = reactive({ + id: undefined as string | number | undefined, + studentName: '', + activityName: '', + score: '', + registrationType: '', + teamName: '' +}); + +const scoreRules = { + score: [{ required: true, message: '请输入成绩', trigger: 'blur' }] +}; + const initFormData: ExtendedActivityRegisterForm = { id: undefined, activityId: props.activityId, @@ -955,6 +1013,48 @@ const handleFileSuccess = (response: any) => { } }; +/** 录入成绩按钮操作 */ +const handleRecordScore = (row: ExtendedStglActivityRegistrationVo) => { + scoreForm.id = row.id; + scoreForm.studentName = row.studentName; + scoreForm.activityName = props.activityName; + scoreForm.score = row.score || ''; + scoreForm.registrationType = row.registrationType?.toString() || ''; + scoreForm.teamName = row.teamName || ''; + scoreDialog.visible = true; +}; + +/** 提交成绩录入 */ +const submitScore = () => { + scoreFormRef.value?.validate(async (valid: boolean) => { + if (valid) { + scoreButtonLoading.value = true; + try { + await recordActivityScore(scoreForm.id!, scoreForm.score); + proxy?.$modal.msgSuccess('成绩录入成功'); + scoreDialog.visible = false; + await getList(); + } catch (error) { + console.error('成绩录入失败:', error); + proxy?.$modal.msgError('成绩录入失败'); + } finally { + scoreButtonLoading.value = false; + } + } + }); +}; + +/** 取消成绩录入 */ +const cancelScore = () => { + scoreDialog.visible = false; + scoreForm.id = undefined; + scoreForm.studentName = ''; + scoreForm.activityName = ''; + scoreForm.score = ''; + scoreForm.registrationType = ''; + scoreForm.teamName = ''; +}; + // 暴露给父组件的方法 defineExpose({ getList diff --git a/web/src/views/stgl/activity/hall/index.vue b/web/src/views/stgl/activity/hall/index.vue index d062539c..1193aafe 100644 --- a/web/src/views/stgl/activity/hall/index.vue +++ b/web/src/views/stgl/activity/hall/index.vue @@ -453,14 +453,17 @@ const getList = async () => { loading.value = true; try { const res = await listRegistrableActivities(queryParams.value); - activityList.value = res.rows; - total.value = res.total; + activityList.value = res.rows || []; + total.value = res.total || 0; // 批量检查用户报名状态 await checkUserRegistrationStatus(); } catch (error) { console.error('查询活动列表失败:', error); proxy?.$modal.msgError('查询活动列表失败'); + // 发生错误时重置数据 + activityList.value = []; + total.value = 0; } finally { loading.value = false; } @@ -468,13 +471,27 @@ const getList = async () => { /** 批量检查用户报名状态 */ const checkUserRegistrationStatus = async () => { + // 防御性检查:确保activityList存在且为数组 + if (!activityList.value || !Array.isArray(activityList.value) || activityList.value.length === 0) { + console.warn('活动列表为空或无效,跳过报名状态检查'); + return; + } + const promises = activityList.value.map(async (activity) => { try { + // 确保activity和activity.id存在 + if (!activity || !activity.id) { + console.warn('活动数据不完整,跳过报名状态检查:', activity); + return; + } + const registered = await checkRegistration(activity.id as number); userRegistrationStatus.value[activity.id as number] = registered.data; } catch (error) { - console.error(`检查活动${activity.id}报名状态失败:`, error); - userRegistrationStatus.value[activity.id as number] = false; + console.error(`检查活动${activity?.id}报名状态失败:`, error); + if (activity?.id) { + userRegistrationStatus.value[activity.id as number] = false; + } } }); diff --git a/web/src/views/stgl/activity/index.vue b/web/src/views/stgl/activity/index.vue index 7322c340..2aa77e05 100644 --- a/web/src/views/stgl/activity/index.vue +++ b/web/src/views/stgl/activity/index.vue @@ -166,6 +166,11 @@ + + +