This commit is contained in:
李旭明 committed 2025-08-27 10:16:15 +08:00
1 parent 93711d76a3
commit 73ffd576bc
63 files changed
+5064 -647

No files matched your search

@@ -20,6 +20,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.dromara.stgl.domain.bo.StglActivityBo;
import org.dromara.stgl.domain.vo.StglActivityVo;
import org.dromara.stgl.domain.vo.ActivityRatingVo;
import org.dromara.stgl.service.IStglActivityService;
import java.util.List;
@@ -106,8 +107,11 @@ public class StglActivityController extends BaseController {
@Log(title = "复制活动信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/copy")
public R<Void> copy(@RequestParam("sourceId") Long sourceId, @RequestParam("newActivityName") String newActivityName) {
return toAjax(stglActivityService.copyActivity(sourceId, newActivityName));
public R<Void> copy(@RequestParam("sourceId") Long sourceId,
@RequestParam("newActivityName") String newActivityName,
@RequestParam(value = "activityStatus", defaultValue = "0") String activityStatus,
@RequestParam(value = "registrationStatus", defaultValue = "0") Integer registrationStatus) {
return toAjax(stglActivityService.copyActivity(sourceId, newActivityName, activityStatus, registrationStatus));
}
/**
@@ -143,4 +147,13 @@ public class StglActivityController extends BaseController {
return R.ok(stglActivityService.queryVolunteerTeamOptions());
}
/**
* 查询活动评分列表
*/
@SaCheckPermission("stgl:activity:query")
@GetMapping("/{id}/ratings")
public R<List<ActivityRatingVo>> getActivityRatings(@NotNull(message = "活动ID不能为空") @PathVariable Long id) {
return R.ok(stglActivityService.getActivityRatings(id));
}
}
@@ -0,0 +1,101 @@
package org.dromara.stgl.controller;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.stgl.domain.vo.StglClassVo;
import org.dromara.stgl.domain.bo.StglClassBo;
import org.dromara.stgl.service.IStglClassService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 班级学生社团、志愿者队伍、活动参加情况
*
* @author Cursor AI
* @date 2025-01-15
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/stgl/stclass")
public class StglClassController extends BaseController {
private final IStglClassService stglClassService;
/**
* 查询班主任的班级列表
*/
@SaCheckPermission("stgl:stclass:list")
@GetMapping("/teacher/classes")
public R<List<Map<String, Object>>> getTeacherClasses() {
Long userId = LoginHelper.getUserId();
List<Map<String, Object>> list = stglClassService.getTeacherClasses(userId);
return R.ok(list);
}
/**
* 查询班级学生社团、志愿者队伍、活动参加情况列表
*/
@SaCheckPermission("stgl:stclass:list")
@GetMapping("/list")
public TableDataInfo<StglClassVo> list(StglClassBo bo, PageQuery pageQuery) {
return stglClassService.queryPageList(bo, pageQuery);
}
/**
* 查询学生社团详情
*/
@SaCheckPermission("stgl:stclass:query")
@GetMapping("/student/clubs/{studentId}")
public R<List<Map<String, Object>>> getStudentClubs(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
List<Map<String, Object>> list = stglClassService.getStudentClubs(studentId);
return R.ok(list);
}
/**
* 查询学生志愿者队伍详情
*/
@SaCheckPermission("stgl:stclass:query")
@GetMapping("/student/volunteer-teams/{studentId}")
public R<List<Map<String, Object>>> getStudentVolunteerTeams(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
List<Map<String, Object>> list = stglClassService.getStudentVolunteerTeams(studentId);
return R.ok(list);
}
/**
* 查询学生活动详情
*/
@SaCheckPermission("stgl:stclass:query")
@GetMapping("/student/activities/{studentId}")
public R<List<Map<String, Object>>> getStudentActivities(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
List<Map<String, Object>> list = stglClassService.getStudentActivities(studentId);
return R.ok(list);
}
/**
* 导出班级学生社团、志愿者队伍、活动参加情况列表
*/
@SaCheckPermission("stgl:stclass:export")
@Log(title = "班级学生社团、志愿者队伍、活动参加情况", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(StglClassBo bo, HttpServletResponse response) {
List<StglClassVo> list = stglClassService.queryList(bo);
ExcelUtil.exportExcel(list, "班级学生参与情况", StglClassVo.class, response);
}
}
@@ -64,8 +64,11 @@ public class StglMyController extends BaseController {
@Operation(summary = "查询我报名的活动列表")
@SaCheckPermission("stgl:my:list")
@GetMapping("/activities")
public R<List<MyActivityVo>> getMyActivities() {
List<MyActivityVo> list = stglMyService.queryMyActivities();
public R<List<MyActivityVo>> getMyActivities(
@Parameter(description = "活动名称") @RequestParam(required = false) String activityName,
@Parameter(description = "活动类型") @RequestParam(required = false) String activityType,
@Parameter(description = "是否评分") @RequestParam(required = false) String isRated) {
List<MyActivityVo> list = stglMyService.queryMyActivities(activityName, activityType, isRated);
return R.ok(list);
}
@@ -52,7 +52,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 查询志愿者成员列表
*/
@SaCheckPermission("stgl:volunteerMember:list")
@SaCheckPermission("stgl:volunteermember:list")
@GetMapping("/list")
public TableDataInfo<StglMemberVo> list(StglMemberBo bo, PageQuery pageQuery) {
bo.setMemberType(2); // 志愿者成员
@@ -62,7 +62,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 导出志愿者成员列表
*/
@SaCheckPermission("stgl:volunteerMember:export")
@SaCheckPermission("stgl:volunteermember:export")
@Log(title = "志愿者成员", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(StglMemberBo bo, HttpServletResponse response) {
@@ -74,7 +74,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 获取志愿者成员详细信息
*/
@SaCheckPermission("stgl:volunteerMember:query")
@SaCheckPermission("stgl:volunteermember:query")
@GetMapping("/{id}")
public R<StglMemberVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
@@ -84,15 +84,15 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 新增志愿者成员
*/
@SaCheckPermission("stgl:volunteerMember:add")
@SaCheckPermission("stgl:volunteermember:add")
@Log(title = "志愿者成员", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody StglMemberBo bo) {
bo.setMemberType(2); // 志愿者成员
// 如果前端没有传递roleType,设置默认值为1(队员)
// 如果前端没有传递roleType,设置默认值为队员
if (bo.getRoleType() == null) {
bo.setRoleType("1");
bo.setRoleType("队员");
}
return toAjax(stglMemberService.insertByBo(bo));
}
@@ -100,7 +100,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 修改志愿者成员
*/
@SaCheckPermission("stgl:volunteerMember:edit")
@SaCheckPermission("stgl:volunteermember:edit")
@Log(title = "志愿者成员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
@@ -112,7 +112,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 删除志愿者成员
*/
@SaCheckPermission("stgl:volunteerMember:remove")
@SaCheckPermission("stgl:volunteermember:remove")
@Log(title = "志愿者成员", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@@ -150,7 +150,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 根据队伍ID查询成员
*/
@SaCheckPermission("stgl:volunteerMember:list")
@SaCheckPermission("stgl:volunteermember:list")
@GetMapping("/team/{teamId}")
public R<List<StglMemberVo>> getTeamMembers(@NotNull(message = "队伍ID不能为空")
@PathVariable Long teamId) {
@@ -164,7 +164,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 批量分配队伍
*/
@SaCheckPermission("stgl:volunteerMember:edit")
@SaCheckPermission("stgl:volunteermember:edit")
@Log(title = "志愿者成员", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/assignTeam")
@@ -175,7 +175,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 获取志愿者成员统计信息
*/
@SaCheckPermission("stgl:volunteerMember:query")
@SaCheckPermission("stgl:volunteermember:query")
@GetMapping("/stats")
public R<Object> getStats() {
return R.ok(stglMemberService.getVolunteerMemberStats());
@@ -185,7 +185,7 @@ public class StglVolunteerMemberController extends BaseController {
* 下载志愿者成员导入模板
*/
@PostMapping("/importTemplate")
@SaCheckPermission("stgl:volunteerMember:import")
@SaCheckPermission("stgl:volunteermember:import")
public void importTemplate(HttpServletResponse response) {
// 创建示例数据
List<StglVolunteerImportVo> templateData = new ArrayList<>();
@@ -211,7 +211,7 @@ public class StglVolunteerMemberController extends BaseController {
/**
* 导入志愿者成员数据
*/
@SaCheckPermission("stgl:volunteerMember:import")
@SaCheckPermission("stgl:volunteermember:import")
@Log(title = "志愿者成员", businessType = BusinessType.IMPORT)
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importData(@RequestPart("file") MultipartFile file,
@@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
@@ -48,9 +49,9 @@ public class StglActivityRating extends TenantEntity {
private String studentName;
/**
* 综合评分(1-5分)
* 综合评分(1-5分,保留1位小数)
*/
private Integer ratingScore;
private BigDecimal ratingScore;
/**
* 评价意见
@@ -2,6 +2,7 @@ package org.dromara.stgl.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
@@ -68,9 +69,46 @@ public class StglActivityTeamInfo extends TenantEntity {
*/
private String description;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableLogic(value = "0", delval = "1")
private Integer deleted;
// 扩展字段(不存储到数据库,用于显示)
/**
* 活动名称
*/
private String activityName;
// 队长详细信息字段(通过关联查询获取)
/**
* 队长性别
*/
private String leaderGender;
/**
* 队长联系电话
*/
private String leaderPhone;
/**
* 队长邮箱
*/
private String leaderEmail;
/**
* 队长院系
*/
private String leaderDepartment;
/**
* 队长专业
*/
private String leaderMajor;
/**
* 队长班级
*/
private String leaderClassName;
}
@@ -0,0 +1,77 @@
package org.dromara.stgl.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 班级学生社团、志愿者队伍、活动参加情况对象 stgl_class
*
* @author Cursor AI
* @date 2025-01-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_student_msg")
public class StglClass extends TenantEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String name;
/**
* 性别
*/
private String gender;
/**
* 联系电话
*/
private String phone;
/**
* 班级ID
*/
private String classId;
/**
* 班级名称
*/
private String className;
/**
* 学院名称
*/
private String collegeName;
/**
* 专业名称
*/
private String majorName;
/**
* 年级
*/
private String grade;
/**
* 学籍状态
*/
private String studentStatus;
}
@@ -117,6 +117,11 @@ public class StglVolunteerTeam extends TenantEntity {
*/
private String advisorEmail;
/**
* 指导老师JSON数据,支持多个指导老师
*/
private String advisorsJson;
/**
* 人员上限
*/
@@ -0,0 +1,74 @@
package org.dromara.stgl.domain.bo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.stgl.domain.StglClass;
/**
* 班级学生社团、志愿者队伍、活动参加情况业务对象 stgl_class
*
* @author Cursor AI
* @date 2025-01-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = StglClass.class, reverseConvertGenerate = false)
public class StglClassBo extends BaseEntity {
/**
* 主键ID
*/
private Long id;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String name;
/**
* 性别
*/
private String gender;
/**
* 联系电话
*/
private String phone;
/**
* 班级ID
*/
private String classId;
/**
* 班级名称
*/
private String className;
/**
* 学院名称
*/
private String collegeName;
/**
* 专业名称
*/
private String majorName;
/**
* 年级
*/
private String grade;
/**
* 学籍状态
*/
private String studentStatus;
}
@@ -138,6 +138,11 @@ public class StglVolunteerTeamBo extends BaseEntity {
@Size(max = 100, message = "指导老师邮箱长度不能超过100个字符")
private String advisorEmail;
/**
* 指导老师JSON数据,支持多个指导老师
*/
private String advisorsJson;
/**
* 人员上限
*/
@@ -0,0 +1,101 @@
package org.dromara.stgl.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.stgl.domain.StglActivityRating;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 活动评分详细信息视图对象
*
* @author ruoyi
* @date 2025-01-07
*/
@Data
@AutoMapper(target = StglActivityRating.class)
public class ActivityRatingVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 评分ID
*/
private Long id;
/**
* 活动ID
*/
private Long activityId;
/**
* 评分人ID
*/
private Long userId;
/**
* 评分人姓名
*/
private String userName;
/**
* 学号
*/
private String studentNo;
/**
* 联系方式
*/
private String phoneNumber;
/**
* 院系名称
*/
private String deptName;
/**
* 专业名称
*/
private String majorName;
/**
* 班级名称
*/
private String className;
/**
* 总评分(1-5分)
*/
private BigDecimal ratingScore;
/**
* 内容评分(1-5分)
*/
private Integer contentScore;
/**
* 组织评分(1-5分)
*/
private Integer organizationScore;
/**
* 体验评分(1-5分)
*/
private Integer experienceScore;
/**
* 评分备注
*/
private String ratingComment;
/**
* 评分时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime ratingTime;
}
@@ -7,6 +7,7 @@ import org.dromara.stgl.domain.StglActivity;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
@@ -110,15 +111,20 @@ public class MyActivityVo implements Serializable {
*/
private String myRegistrationStatus;
/**
* 报名类型(1-个人 2-团队)
*/
private String registrationType;
/**
* 我的评分状态(0-未评分 1-已评分)
*/
private Integer myRatingStatus;
/**
* 我的综合评分
* 我的综合评分(保留1位小数)
*/
private Integer myRatingScore;
private BigDecimal myRatingScore;
/**
* 我的评分时间
@@ -52,6 +52,11 @@ public class MyVolunteerTeamVo implements Serializable {
*/
private String advisorDept;
/**
* 指导老师JSON数据,支持多个指导老师
*/
private String advisorsJson;
/**
* 当前成员数量
*/
@@ -0,0 +1,104 @@
package org.dromara.stgl.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.stgl.domain.StglClass;
import java.io.Serializable;
import java.util.Date;
/**
* 班级学生社团、志愿者队伍、活动参加情况视图对象 stgl_class
*
* @author Cursor AI
* @date 2025-01-15
*/
@Data
@AutoMapper(target = StglClass.class)
public class StglClassVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 学号
*/
private String studentNo;
/**
* 学生姓名
*/
private String studentName;
/**
* 性别
*/
private String gender;
/**
* 联系电话
*/
private String phone;
/**
* 班级名称
*/
private String className;
/**
* 加入社团数量
*/
private Integer clubCount;
/**
* 加入志愿者队伍数量
*/
private Integer volunteerTeamCount;
/**
* 参与活动数量
*/
private Integer activityCount;
/**
* 创建者
*/
private Long createBy;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新者
*/
private Long updateBy;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 租户编号
*/
private String tenantId;
/**
* 版本号
*/
private Long version;
/**
* 逻辑删除
*/
private Long deleted;
}
@@ -137,6 +137,11 @@ public class StglVolunteerTeamVo implements Serializable {
@ExcelProperty(value = "指导老师邮箱")
private String advisorEmail;
/**
* 指导老师JSON数据,支持多个指导老师
*/
private String advisorsJson;
/**
* 人员上限
*/
@@ -238,7 +238,7 @@ public class StglVolunteerImportListener extends AnalysisEventListener<StglVolun
newMember.setStudentName(volunteerVo.getStudentName());
// 🔑 关键修复:设置用户ID(学生ID就是用户ID)
newMember.setUserId(student.getId());
newMember.setRoleType("1"); // 志愿者角色 stgl_volunteer_role=1 队员
newMember.setRoleType("队员"); // 队员角色 - 直接写入字符"队员"
newMember.setStatus("2"); // 成员状态 stgl_member_status=2 已加入
newMember.setJoinTime(volunteerVo.getJoinTime() != null ? volunteerVo.getJoinTime() : new Date());
@@ -3,6 +3,9 @@ package org.dromara.stgl.mapper;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.stgl.domain.StglActivityRating;
import org.dromara.stgl.domain.vo.ActivityRatingVo;
import java.util.List;
/**
* 活动评分数据访问层
@@ -40,4 +43,12 @@ public interface StglActivityRatingMapper extends BaseMapperPlus<StglActivityRat
*/
Double selectAverageRatingByActivityId(@Param("activityId") Long activityId);
/**
* 查询活动评分详情(关联用户表获取详细信息)
*
* @param activityId 活动ID
* @return 评分详细信息列表
*/
List<ActivityRatingVo> selectActivityRatingsWithUserInfo(@Param("activityId") Long activityId);
}
@@ -1,9 +1,13 @@
package org.dromara.stgl.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.dromara.stgl.domain.StglActivityTeamInfo;
import org.dromara.stgl.domain.vo.StglActivityTeamInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 活动团队信息Mapper接口
@@ -13,4 +17,19 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
*/
public interface StglActivityTeamInfoMapper extends BaseMapperPlus<StglActivityTeamInfo, StglActivityTeamInfoVo> {
/**
* 根据条件查询团队信息列表(VO对象)
*
* @param queryWrapper 查询条件
* @return 团队信息列表
*/
List<StglActivityTeamInfoVo> selectVoList(@Param(Constants.WRAPPER) Wrapper<StglActivityTeamInfo> queryWrapper);
/**
* 根据活动ID查询团队列表
*
* @param activityId 活动ID
* @return 团队列表
*/
List<StglActivityTeamInfoVo> selectVoListByActivityId(@Param("activityId") Long activityId);
}
@@ -0,0 +1,65 @@
package org.dromara.stgl.mapper;
import org.dromara.stgl.domain.StglClass;
import org.dromara.stgl.domain.vo.StglClassVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
import java.util.Map;
/**
* 班级学生社团、志愿者队伍、活动参加情况Mapper接口
*
* @author Cursor AI
* @date 2025-01-15
*/
public interface StglClassMapper extends BaseMapperPlus<StglClass, StglClassVo> {
/**
* 查询班主任的班级列表
*
* @param userId 用户ID
* @return 班级列表
*/
List<Map<String, Object>> selectTeacherClasses(Long userId);
/**
* 查询班级学生列表(包含社团、志愿者队伍、活动统计)
*
* @param params 查询参数
* @return 学生列表
*/
List<StglClassVo> selectClassStudents(Map<String, Object> params);
/**
* 查询班级学生总数
*
* @param params 查询参数
* @return 学生总数
*/
Integer selectClassStudentsCount(Map<String, Object> params);
/**
* 查询学生社团详情
*
* @param studentId 学生ID
* @return 社团详情列表
*/
List<Map<String, Object>> selectStudentClubs(Long studentId);
/**
* 查询学生志愿者队伍详情
*
* @param studentId 学生ID
* @return 志愿者队伍详情列表
*/
List<Map<String, Object>> selectStudentVolunteerTeams(Long studentId);
/**
* 查询学生活动详情
*
* @param studentId 学生ID
* @return 活动详情列表
*/
List<Map<String, Object>> selectStudentActivities(Long studentId);
}
@@ -40,9 +40,14 @@ public interface StglMyMapper {
*
* @param userId 用户ID
* @param tenantId 租户ID
* @param activityName 活动名称
* @param activityType 活动类型
* @param isRated 是否评分
* @return 活动列表
*/
List<MyActivityVo> selectMyActivities(@Param("userId") Long userId, @Param("tenantId") String tenantId);
List<MyActivityVo> selectMyActivities(@Param("userId") Long userId, @Param("tenantId") String tenantId,
@Param("activityName") String activityName, @Param("activityType") String activityType,
@Param("isRated") String isRated);
/**
* 分页查询我的报名记录(社团+志愿团队+活动)
@@ -6,6 +6,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.stgl.domain.StglActivity;
import org.dromara.stgl.domain.bo.StglActivityBo;
import org.dromara.stgl.domain.vo.StglActivityVo;
import org.dromara.stgl.domain.vo.ActivityRatingVo;
import java.util.Collection;
import java.util.List;
@@ -82,9 +83,11 @@ public interface IStglActivityService extends IService<StglActivity> {
*
* @param sourceId 源活动ID
* @param newActivityName 新活动名称
* @param activityStatus 新活动状态
* @param registrationStatus 新活动报名状态
* @return 是否成功
*/
Boolean copyActivity(Long sourceId, String newActivityName);
Boolean copyActivity(Long sourceId, String newActivityName, String activityStatus, Integer registrationStatus);
/**
* 查询社团选择器选项
@@ -112,4 +115,12 @@ public interface IStglActivityService extends IService<StglActivity> {
*/
Boolean summarizeActivity(Long id, String summary, String achievements, String summaryAttachments, String achievementsAttachments);
/**
* 查询活动评分列表(包含评分人详细信息)
*
* @param activityId 活动ID
* @return 活动评分详细信息列表
*/
List<ActivityRatingVo> getActivityRatings(Long activityId);
}
@@ -0,0 +1,68 @@
package org.dromara.stgl.service;
import org.dromara.stgl.domain.vo.StglClassVo;
import org.dromara.stgl.domain.bo.StglClassBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 班级学生社团、志愿者队伍、活动参加情况Service接口
*
* @author Cursor AI
* @date 2025-01-15
*/
public interface IStglClassService {
/**
* 查询班主任的班级列表
*
* @param userId 用户ID
* @return 班级列表
*/
List<Map<String, Object>> getTeacherClasses(Long userId);
/**
* 查询班级学生社团、志愿者队伍、活动参加情况分页列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 分页结果
*/
TableDataInfo<StglClassVo> queryPageList(StglClassBo bo, PageQuery pageQuery);
/**
* 查询班级学生社团、志愿者队伍、活动参加情况列表
*
* @param bo 查询条件
* @return 列表结果
*/
List<StglClassVo> queryList(StglClassBo bo);
/**
* 查询学生社团详情
*
* @param studentId 学生ID
* @return 社团详情列表
*/
List<Map<String, Object>> getStudentClubs(Long studentId);
/**
* 查询学生志愿者队伍详情
*
* @param studentId 学生ID
* @return 志愿者队伍详情列表
*/
List<Map<String, Object>> getStudentVolunteerTeams(Long studentId);
/**
* 查询学生活动详情
*
* @param studentId 学生ID
* @return 活动详情列表
*/
List<Map<String, Object>> getStudentActivities(Long studentId);
}
@@ -35,9 +35,12 @@ public interface IStglMyService {
/**
* 查询我报名的活动列表(带评分状态)
*
* @param activityName 活动名称
* @param activityType 活动类型
* @param isRated 是否评分
* @return 活动列表
*/
List<MyActivityVo> queryMyActivities();
List<MyActivityVo> queryMyActivities(String activityName, String activityType, String isRated);
/**
* 分页查询我的报名记录
@@ -16,8 +16,10 @@ import org.dromara.stgl.domain.StglActivityTeamInfo;
import org.dromara.stgl.domain.bo.StglActivityRegistrationBo;
import org.dromara.stgl.domain.bo.StglActivityTeamInfoBo;
import org.dromara.stgl.domain.vo.StglActivityRegistrationVo;
import org.dromara.stgl.domain.vo.StglActivityVo;
import org.dromara.stgl.mapper.StglActivityRegistrationMapper;
import org.dromara.stgl.service.IStglActivityRegistrationService;
import org.dromara.stgl.service.IStglActivityService;
import org.dromara.stgl.service.IStglActivityTeamInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -38,6 +40,7 @@ import java.util.List;
public class StglActivityRegistrationServiceImpl extends ServiceImpl<StglActivityRegistrationMapper, StglActivityRegistration> implements IStglActivityRegistrationService {
private final StglActivityRegistrationMapper baseMapper;
private final IStglActivityService stglActivityService;
private final IStglActivityTeamInfoService teamInfoService;
/**
@@ -192,9 +195,19 @@ public class StglActivityRegistrationServiceImpl extends ServiceImpl<StglActivit
throw new RuntimeException("您已报名该活动,请勿重复报名");
}
// 设置报名时间和状态
// 设置报名时间
bo.setRegistrationTime(new Date());
bo.setApprovalStatus("0"); // 待审核
// 如果没有设置审核状态,则根据活动的审核设置来决定
if (bo.getApprovalStatus() == null) {
// 获取活动信息,检查是否需要审核
StglActivityVo activity = stglActivityService.queryById(bo.getActivityId());
if (activity != null && activity.getNeedApproval() != null && activity.getNeedApproval() == 0) {
bo.setApprovalStatus("1"); // 无需审核,自动通过
} else {
bo.setApprovalStatus("0"); // 需要审核,待审核
}
}
// 如果是团队报名,需要先创建团队信息
if ("2".equals(bo.getRegistrationType()) && bo.getTeamId() == null) {
@@ -19,7 +19,9 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.stgl.domain.StglActivity;
import org.dromara.stgl.domain.bo.StglActivityBo;
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.service.IStglActivityService;
import org.dromara.stgl.utils.AdvisorRoleAssigner;
import org.springframework.stereotype.Service;
@@ -42,6 +44,9 @@ import org.dromara.stgl.domain.StglClub;
import org.dromara.stgl.domain.StglVolunteerTeam;
import org.dromara.stgl.mapper.StglClubMapper;
import org.dromara.stgl.mapper.StglVolunteerTeamMapper;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysUserService;
/**
* 活动信息Service业务层处理
@@ -58,6 +63,8 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
private final AdvisorRoleAssigner advisorRoleAssigner;
private final StglClubMapper stglClubMapper;
private final StglVolunteerTeamMapper stglVolunteerTeamMapper;
private final StglActivityRatingMapper stglActivityRatingMapper;
private final ISysUserService sysUserService;
/**
* 查询活动信息
@@ -336,7 +343,7 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean copyActivity(Long sourceId, String newActivityName) {
public Boolean copyActivity(Long sourceId, String newActivityName, String activityStatus, Integer registrationStatus) {
StglActivityVo sourceActivity = queryById(sourceId);
if (sourceActivity == null) {
throw new RuntimeException("源活动不存在");
@@ -367,8 +374,8 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
// 设置业务字段
newActivityEntity.setActivityName(newActivityName);
newActivityEntity.setActivityStatus("1"); // 默认筹备中
newActivityEntity.setRegistrationStatus(0); // 默认未开始
newActivityEntity.setActivityStatus(activityStatus); // 使用传递的活动状态参数
newActivityEntity.setRegistrationStatus(registrationStatus); // 使用传递的报名状态参数
newActivityEntity.setIsFinished(0); // 设置为未完成
newActivityEntity.setSummary(null); // 清空总结
newActivityEntity.setAchievements(null); // 清空成果
@@ -552,7 +559,7 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
log.info("应用数据权限:用户 {} 为社长角色,只能查看自己创建的活动", currentUserId);
}
// 🔥 新增:如果是stgl_instructor角色且不是管理员,只能查看自己作为指导老师的社团的活动
// 🔥 修正:如果是stgl_instructor角色且不是管理员,只能查看自己作为指导老师的活动
if (roleKeys.contains("stgl_instructor") &&
!roleKeys.contains("admin") &&
!roleKeys.contains("common")) {
@@ -560,24 +567,20 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
// 获取用户作为指导老师的社团ID列表
List<Long> 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);
// 获取用户作为指导老师的志愿者队伍ID列表
List<Long> userAdvisorTeamIds = getUserAdvisorTeamIds(currentUserId);
// 获取用户作为指导老师的活动ID列表
List<Long> userAdvisorActivityIds = getUserAdvisorActivityIds(currentUserId);
// 构建数据权限过滤条件
String dataScope = buildInstructorDataScope(userAdvisorClubIds, userAdvisorTeamIds, userAdvisorActivityIds);
if (bo.getParams() == null) {
bo.setParams(new HashMap<>());
}
bo.getParams().put("dataScope", dataScope);
log.info("应用数据权限:用户 {} 为指导老师角色,数据权限条件: {}", currentUserId, dataScope);
}
} catch (Exception e) {
@@ -634,4 +637,195 @@ public class StglActivityServiceImpl extends ServiceImpl<StglActivityMapper, Stg
return clubIds;
}
/**
* 获取用户作为指导老师的志愿者队伍ID列表
*
* @param userId 用户ID
* @return 志愿者队伍ID列表
*/
private List<Long> getUserAdvisorTeamIds(Long userId) {
List<Long> teamIds = new ArrayList<>();
try {
// 从stgl_volunteer_team表的advisor_name字段查询
List<Long> nameTeamIds = getNameAdvisorTeamIds(userId);
teamIds.addAll(nameTeamIds);
// 从stgl_volunteer_team表的advisors_json字段查询
List<Long> jsonTeamIds = getJsonAdvisorTeamIds(userId);
teamIds.addAll(jsonTeamIds);
log.debug("用户 {} 作为指导老师的志愿者队伍ID列表: {}", userId, teamIds);
} catch (Exception e) {
log.error("获取用户 {} 作为指导老师的志愿者队伍ID列表时发生异常: {}", userId, e.getMessage(), e);
}
return teamIds;
}
/**
* 从志愿者队伍表的advisor_name字段获取用户作为指导老师的志愿者队伍ID列表
*
* @param userId 用户ID
* @return 志愿者队伍ID列表
*/
private List<Long> getNameAdvisorTeamIds(Long userId) {
List<Long> teamIds = new ArrayList<>();
try {
// 先通过用户ID查询用户信息,获取用户姓名
SysUserVo user = sysUserService.selectUserById(userId);
if (user != null && StringUtils.isNotBlank(user.getNickName())) {
// 查询志愿者队伍表中advisor_name字段匹配该用户姓名的记录
LambdaQueryWrapper<StglVolunteerTeam> lqw = new LambdaQueryWrapper<>();
lqw.select(StglVolunteerTeam::getId);
lqw.eq(StglVolunteerTeam::getAdvisorName, user.getNickName());
List<StglVolunteerTeam> teams = stglVolunteerTeamMapper.selectList(lqw);
teamIds = teams.stream()
.map(StglVolunteerTeam::getId)
.collect(Collectors.toList());
}
} catch (Exception e) {
log.error("从志愿者队伍表获取用户 {} 作为指导老师的志愿者队伍ID列表时发生异常: {}", userId, e.getMessage(), e);
}
return teamIds;
}
/**
* 从志愿者队伍表的advisors_json字段获取用户作为指导老师的志愿者队伍ID列表
*
* @param userId 用户ID
* @return 志愿者队伍ID列表
*/
private List<Long> getJsonAdvisorTeamIds(Long userId) {
List<Long> teamIds = new ArrayList<>();
try {
// 查询志愿者队伍表中advisors_json字段包含该用户的记录
LambdaQueryWrapper<StglVolunteerTeam> lqw = new LambdaQueryWrapper<>();
lqw.select(StglVolunteerTeam::getId);
lqw.isNotNull(StglVolunteerTeam::getAdvisorsJson);
lqw.ne(StglVolunteerTeam::getAdvisorsJson, "");
lqw.like(StglVolunteerTeam::getAdvisorsJson, userId.toString());
List<StglVolunteerTeam> teams = stglVolunteerTeamMapper.selectList(lqw);
teamIds = teams.stream()
.map(StglVolunteerTeam::getId)
.collect(Collectors.toList());
} catch (Exception e) {
log.error("从志愿者队伍表获取用户 {} 作为指导老师的志愿者队伍ID列表时发生异常: {}", userId, e.getMessage(), e);
}
return teamIds;
}
/**
* 获取用户作为指导老师的活动ID列表
*
* @param userId 用户ID
* @return 活动ID列表
*/
private List<Long> getUserAdvisorActivityIds(Long userId) {
List<Long> activityIds = new ArrayList<>();
try {
// 从stgl_activity表的instructors字段查询
List<Long> jsonActivityIds = getJsonAdvisorActivityIds(userId);
activityIds.addAll(jsonActivityIds);
log.debug("用户 {} 作为指导老师的活动ID列表: {}", userId, activityIds);
} catch (Exception e) {
log.error("获取用户 {} 作为指导老师的活动ID列表时发生异常: {}", userId, e.getMessage(), e);
}
return activityIds;
}
/**
* 从活动表的instructors字段获取用户作为指导老师的活动ID列表
*
* @param userId 用户ID
* @return 活动ID列表
*/
private List<Long> getJsonAdvisorActivityIds(Long userId) {
List<Long> activityIds = new ArrayList<>();
try {
// 查询活动表中instructors字段包含该用户的记录
LambdaQueryWrapper<StglActivity> lqw = new LambdaQueryWrapper<>();
lqw.select(StglActivity::getId);
lqw.like(StglActivity::getInstructors, userId.toString());
List<StglActivity> activities = baseMapper.selectList(lqw);
activityIds = activities.stream()
.map(StglActivity::getId)
.collect(Collectors.toList());
} catch (Exception e) {
log.error("从活动表获取用户 {} 作为指导老师的活动ID列表时发生异常: {}", userId, e.getMessage(), e);
}
return activityIds;
}
/**
* 构建指导老师数据权限过滤条件
*
* @param userAdvisorClubIds 用户作为指导老师的社团ID列表
* @param userAdvisorTeamIds 用户作为指导老师的志愿者队伍ID列表
* @param userAdvisorActivityIds 用户作为指导老师的活动ID列表
* @return 数据权限过滤条件
*/
private String buildInstructorDataScope(List<Long> userAdvisorClubIds, List<Long> userAdvisorTeamIds, List<Long> userAdvisorActivityIds) {
List<String> conditions = new ArrayList<>();
// 1. 是活动关联社团的指导老师
if (!userAdvisorClubIds.isEmpty()) {
String clubIdsStr = userAdvisorClubIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
conditions.add("(sa.related_type = 1 AND sa.related_club_id IN (" + clubIdsStr + "))");
}
// 2. 是活动关联志愿者队伍的指导老师
if (!userAdvisorTeamIds.isEmpty()) {
String teamIdsStr = userAdvisorTeamIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
conditions.add("(sa.related_type = 2 AND sa.related_club_id IN (" + teamIdsStr + "))");
}
// 3. 是活动本身的指导老师
if (!userAdvisorActivityIds.isEmpty()) {
String activityIdsStr = userAdvisorActivityIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
conditions.add("sa.id IN (" + activityIdsStr + ")");
}
// 如果没有任何权限,返回一个永远为false的条件
if (conditions.isEmpty()) {
return "AND 1 = 0";
}
// 组合所有条件,使用OR连接
return "AND (" + String.join(" OR ", conditions) + ")";
}
@Override
public List<ActivityRatingVo> getActivityRatings(Long activityId) {
if (activityId == null) {
return new ArrayList<>();
}
// 使用自定义SQL查询评分详情,关联用户表获取完整信息
return stglActivityRatingMapper.selectActivityRatingsWithUserInfo(activityId);
}
}
@@ -118,7 +118,6 @@ public class StglActivityTeamInfoServiceImpl extends ServiceImpl<StglActivityTea
public List<StglActivityTeamInfoVo> queryByActivityId(Long activityId) {
LambdaQueryWrapper<StglActivityTeamInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(StglActivityTeamInfo::getActivityId, activityId);
lqw.orderByDesc(StglActivityTeamInfo::getCreateTime);
return baseMapper.selectVoList(lqw);
}
@@ -0,0 +1,152 @@
package org.dromara.stgl.service.impl;
import org.dromara.stgl.domain.StglClass;
import org.dromara.stgl.domain.vo.StglClassVo;
import org.dromara.stgl.domain.bo.StglClassBo;
import org.dromara.stgl.mapper.StglClassMapper;
import org.dromara.stgl.service.IStglClassService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 班级学生社团、志愿者队伍、活动参加情况Service业务层处理
*
* @author Cursor AI
* @date 2025-01-15
*/
@RequiredArgsConstructor
@Service
public class StglClassServiceImpl implements IStglClassService {
private final StglClassMapper baseMapper;
/**
* 查询班主任的班级列表
*
* @param userId 用户ID
* @return 班级列表
*/
@Override
public List<Map<String, Object>> getTeacherClasses(Long userId) {
return baseMapper.selectTeacherClasses(userId);
}
/**
* 查询班级学生社团、志愿者队伍、活动参加情况分页列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 分页结果
*/
@Override
public TableDataInfo<StglClassVo> queryPageList(StglClassBo bo, PageQuery pageQuery) {
// 构建查询参数
Map<String, Object> params = buildQueryParams(bo);
params.put("offset", (pageQuery.getPageNum() - 1) * pageQuery.getPageSize());
params.put("pageSize", pageQuery.getPageSize());
// 使用自定义SQL查询
List<StglClassVo> list = baseMapper.selectClassStudents(params);
// 获取总数
Map<String, Object> countParams = buildQueryParams(bo);
Integer total = baseMapper.selectClassStudentsCount(countParams);
TableDataInfo<StglClassVo> result = new TableDataInfo<>();
result.setRows(list);
result.setTotal(total != null ? total : 0);
return result;
}
/**
* 查询班级学生社团、志愿者队伍、活动参加情况列表
*
* @param bo 查询条件
* @return 列表结果
*/
@Override
public List<StglClassVo> queryList(StglClassBo bo) {
LambdaQueryWrapper<StglClass> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
/**
* 查询学生社团详情
*
* @param studentId 学生ID
* @return 社团详情列表
*/
@Override
public List<Map<String, Object>> getStudentClubs(Long studentId) {
return baseMapper.selectStudentClubs(studentId);
}
/**
* 查询学生志愿者队伍详情
*
* @param studentId 学生ID
* @return 志愿者队伍详情列表
*/
@Override
public List<Map<String, Object>> getStudentVolunteerTeams(Long studentId) {
return baseMapper.selectStudentVolunteerTeams(studentId);
}
/**
* 查询学生活动详情
*
* @param studentId 学生ID
* @return 活动详情列表
*/
@Override
public List<Map<String, Object>> getStudentActivities(Long studentId) {
return baseMapper.selectStudentActivities(studentId);
}
/**
* 构建查询参数
*
* @param bo 查询条件
* @return 查询参数
*/
private Map<String, Object> buildQueryParams(StglClassBo bo) {
Map<String, Object> params = bo.getParams();
if (StringUtils.isNotBlank(bo.getClassId())) {
params.put("classId", bo.getClassId());
}
if (StringUtils.isNotBlank(bo.getName())) {
params.put("studentName", bo.getName());
}
if (StringUtils.isNotBlank(bo.getStudentNo())) {
params.put("studentNo", bo.getStudentNo());
}
return params;
}
/**
* 构建查询条件
*
* @param bo 查询条件
* @return 查询条件
*/
private LambdaQueryWrapper<StglClass> buildQueryWrapper(StglClassBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<StglClass> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getClassId()), StglClass::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getName()), StglClass::getName, bo.getName());
lqw.like(StringUtils.isNotBlank(bo.getStudentNo()), StglClass::getStudentNo, bo.getStudentNo());
return lqw;
}
}
@@ -25,6 +25,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
// 添加学生信息服务依赖
import org.dromara.xg.domain.XgStudentMsg;
import org.dromara.xg.mapper.XgStudentMsgMapper;
// 添加社长角色分配相关依赖
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.mapper.SysUserRoleMapper;
import java.util.stream.Collectors;
import java.util.Collections;
import org.dromara.common.satoken.utils.LoginHelper;
@@ -56,6 +59,9 @@ import java.util.Set;
public class StglClubServiceImpl implements IStglClubService {
private static final Logger log = LoggerFactory.getLogger(StglClubServiceImpl.class);
// 社长角色ID常量
private static final Long CLUB_PRESIDENT_ROLE_ID = 1957336212742184962L;
private final StglClubMapper baseMapper;
private final StglMemberMapper memberMapper;
@@ -63,6 +69,8 @@ public class StglClubServiceImpl implements IStglClubService {
private final XgStudentMsgMapper studentMsgMapper;
// 添加指导老师角色分配工具
private final AdvisorRoleAssigner advisorRoleAssigner;
// 添加用户角色Mapper
private final SysUserRoleMapper sysUserRoleMapper;
/**
* 查询社团信息
@@ -332,6 +340,8 @@ public class StglClubServiceImpl implements IStglClubService {
createLeaderMemberRecords(add);
// 为指导老师分配角色
assignAdvisorRoles(add);
// 为社长分配角色
assignPresidentRole(add);
}
return flag;
}
@@ -1095,6 +1105,23 @@ public class StglClubServiceImpl implements IStglClubService {
memberMapper.insert(newMember);
}
// 8. 处理社长角色分配:移除原社长角色,为新社长分配角色
try {
// 8.1 移除原社长的角色(根据社团信息获取原社长的用户ID)
Long oldPresidentUserId = findUserIdByStudentNo(club.getPresidentStudentNo());
if (oldPresidentUserId != null) {
removePresidentRole(oldPresidentUserId);
log.info("社团转让:成功移除原社长角色,用户ID: {}, 社团: {}", oldPresidentUserId, club.getClubName());
}
// 8.2 为新社长分配角色
assignPresidentRoleByUserId(newPresidentUserId, club.getClubName());
log.info("社团转让:成功为新社长分配角色,用户ID: {}, 社团: {}", newPresidentUserId, club.getClubName());
} catch (Exception e) {
log.error("社团转让时角色分配出现异常,社团: {}", club.getClubName(), e);
// 注意:这里不抛出异常,避免影响转让主流程
}
return true;
}
@@ -1207,5 +1234,104 @@ public class StglClubServiceImpl implements IStglClubService {
return advisorUserIds;
}
/**
* 为社长分配角色
*
* @param club 社团信息
*/
private void assignPresidentRole(StglClub club) {
try {
if (StringUtils.isNotBlank(club.getPresidentStudentNo())) {
// 根据学号查找用户ID
Long presidentUserId = findUserIdByStudentNo(club.getPresidentStudentNo());
if (presidentUserId != null) {
assignPresidentRoleByUserId(presidentUserId, club.getClubName());
} else {
log.warn("社团 {} 的社长学号 {} 对应的用户不存在,跳过角色分配",
club.getClubName(), club.getPresidentStudentNo());
}
} else {
log.warn("社团 {} 的社长学号为空,跳过角色分配", club.getClubName());
}
} catch (Exception e) {
log.error("为社团 {} 的社长分配角色时发生异常", club.getClubName(), e);
// 不抛出异常,避免影响主业务流程
}
}
/**
* 根据用户ID为社长分配角色
*
* @param presidentUserId 社长用户ID
* @param clubName 社团名称
*/
private void assignPresidentRoleByUserId(Long presidentUserId, String clubName) {
try {
// 检查用户是否已有该角色
if (!hasUserRole(presidentUserId, CLUB_PRESIDENT_ROLE_ID)) {
SysUserRole userRole = new SysUserRole();
userRole.setUserId(presidentUserId);
userRole.setRoleId(CLUB_PRESIDENT_ROLE_ID);
int result = sysUserRoleMapper.insert(userRole);
if (result > 0) {
log.info("成功为社团 {} 的社长分配角色,社长用户ID: {}, 角色ID: {}",
clubName, presidentUserId, CLUB_PRESIDENT_ROLE_ID);
} else {
log.error("为社团 {} 的社长分配角色失败,社长用户ID: {}", clubName, presidentUserId);
}
} else {
log.debug("社团 {} 的社长已有该角色,跳过分配", clubName);
}
} catch (Exception e) {
log.error("为社团 {} 的社长分配角色时发生异常,社长用户ID: {}", clubName, presidentUserId, e);
throw new RuntimeException("分配社长角色失败", e);
}
}
/**
* 移除社长角色
*
* @param presidentUserId 社长用户ID
*/
private void removePresidentRole(Long presidentUserId) {
try {
int result = sysUserRoleMapper.delete(
Wrappers.<SysUserRole>lambdaQuery()
.eq(SysUserRole::getUserId, presidentUserId)
.eq(SysUserRole::getRoleId, CLUB_PRESIDENT_ROLE_ID)
);
if (result > 0) {
log.info("成功移除用户 {} 的社长角色", presidentUserId);
} else {
log.debug("用户 {} 没有社长角色需要移除", presidentUserId);
}
} catch (Exception e) {
log.error("移除用户 {} 的社长角色时发生异常", presidentUserId, e);
throw new RuntimeException("移除社长角色失败", e);
}
}
/**
* 检查用户是否已有指定角色
*
* @param userId 用户ID
* @param roleId 角色ID
* @return 是否已有该角色
*/
private boolean hasUserRole(Long userId, Long roleId) {
try {
LambdaQueryWrapper<SysUserRole> query = Wrappers.lambdaQuery();
query.eq(SysUserRole::getUserId, userId)
.eq(SysUserRole::getRoleId, roleId);
return sysUserRoleMapper.selectCount(query) > 0;
} catch (Exception e) {
log.error("检查用户角色关系时发生异常,用户ID: {}, 角色ID: {}", userId, roleId, e);
// 如果查询失败,假设用户没有该角色,继续分配
return false;
}
}
}
@@ -28,6 +28,7 @@ import java.util.Date;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
/**
@@ -150,13 +151,16 @@ public class StglMemberServiceImpl implements IStglMemberService {
// 处理状态查询:优先使用statusList多状态查询,如果没有则使用单个status
if (params != null && params.get("statusList") != null) {
Object statusList = params.get("statusList");
log.info("StglMemberServiceImpl - statusList参数: {}, 类型: {}", statusList, statusList.getClass());
if (statusList instanceof List) {
List<?> statuses = (List<?>) statusList;
if (!statuses.isEmpty()) {
log.info("StglMemberServiceImpl - 使用List类型statusList: {}", statuses);
lqw.in(StglMember::getStatus, statuses);
}
} else if (statusList instanceof String) {
String statusStr = (String) statusList;
log.info("StglMemberServiceImpl - 使用String类型statusList: {}", statusStr);
if (statusStr.contains(",")) {
// 处理 "0,3" 格式的字符串
String[] statuses = statusStr.split(",");
@@ -164,15 +168,20 @@ public class StglMemberServiceImpl implements IStglMemberService {
for (String status : statuses) {
statusList2.add(status.trim());
}
log.info("StglMemberServiceImpl - 解析后的statusList: {}", statusList2);
lqw.in(StglMember::getStatus, statusList2);
} else {
// 单个状态值
log.info("StglMemberServiceImpl - 单个状态值: {}", statusStr);
lqw.eq(StglMember::getStatus, statusStr);
}
}
} else if (bo.getStatus() != null) {
// 如果没有statusList,则使用单个status字段
log.info("StglMemberServiceImpl - 使用单个status: {}", bo.getStatus());
lqw.eq(StglMember::getStatus, bo.getStatus());
} else {
log.info("StglMemberServiceImpl - 无状态过滤条件");
}
lqw.between(params.get("beginJoinTime") != null && params.get("endJoinTime") != null,
@@ -238,7 +247,14 @@ public class StglMemberServiceImpl implements IStglMemberService {
entity.setStatus(2); // 默认为已加入状态(stgl_member_status字典)
}
if (entity.getRoleType() == null) {
entity.setRoleType("3"); // 默认为普通成员
// 根据成员类型设置不同的默认角色
if (entity.getMemberType() != null && entity.getMemberType() == 2) {
// 志愿者成员默认角色为"队员"
entity.setRoleType("队员");
} else {
// 社团成员默认角色为"3"(普通成员)
entity.setRoleType("3");
}
}
}
@@ -319,7 +335,16 @@ public class StglMemberServiceImpl implements IStglMemberService {
member.setMemberType(memberType);
member.setRelationId(relationId);
member.setUserId(userId);
member.setRoleType(roleType != null ? roleType.toString() : "3");
// 根据成员类型设置不同的默认角色
if (roleType != null) {
member.setRoleType(roleType.toString());
} else if (memberType == 2) {
// 志愿者成员默认角色为"队员"
member.setRoleType("队员");
} else {
// 社团成员默认角色为"3"
member.setRoleType("3");
}
member.setJoinTime(now);
member.setStatus(2); // 已加入状态(stgl_member_status字典)
return member;
@@ -425,7 +450,16 @@ 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"); // 默认普通成员
// 根据成员类型设置不同的默认角色
if (memberVo.getRoleType() != null) {
memberBo.setRoleType(memberVo.getRoleType());
} else if (memberType == 2) {
// 志愿者成员默认角色为"队员"
memberBo.setRoleType("队员");
} else {
// 社团成员默认角色为"1"
memberBo.setRoleType("1");
}
memberBo.setStatus(memberVo.getStatus() != null ? memberVo.getStatus() : "1"); // 默认正常状态
memberBo.setJoinTime(memberVo.getJoinTime() != null ? memberVo.getJoinTime() : new Date());
@@ -584,22 +618,30 @@ public class StglMemberServiceImpl implements IStglMemberService {
return bo; // 不做任何过滤
}
// 如果是志愿者队长,只能查看自己担任队长的队伍成员
// 如果是志愿者队长,可以查看自己担任队长的队伍成员,或者自己所在的队伍成员
if (roles.contains("stgl_volunteer_captain")) {
// 查询用户担任队长的队伍ID列表
List<Long> captainTeamIds = getCaptainTeamIds(currentUserId);
if (captainTeamIds.isEmpty()) {
// 如果用户不是任何队伍的队长,返回空结果
// 查询用户作为成员所在的志愿者队伍ID列表
List<Long> memberTeamIds = getMemberTeamIds(currentUserId);
// 合并队长和成员的队伍ID列表
Set<Long> accessibleTeamIds = new HashSet<>();
accessibleTeamIds.addAll(captainTeamIds);
accessibleTeamIds.addAll(memberTeamIds);
if (accessibleTeamIds.isEmpty()) {
// 如果用户不在任何志愿者队伍中,返回空结果
bo.setRelationId(-1L); // 设置一个不存在的关联ID
} else if (bo.getRelationId() == null) {
// 如果没有指定特定队伍,限制查询范围为该用户担任队长的队伍
// 如果没有指定特定队伍,限制查询范围为该用户有权限访问的队伍
// 由于查询接口限制,我们只能返回第一个队伍的数据
// 在实际应用中,前端应该明确指定要查询的队伍ID
bo.setRelationId(captainTeamIds.get(0));
bo.setRelationId(accessibleTeamIds.iterator().next());
} else {
// 如果指定了队伍ID,验证用户是否有权限访问该队伍
if (!captainTeamIds.contains(bo.getRelationId())) {
if (!accessibleTeamIds.contains(bo.getRelationId())) {
bo.setRelationId(-1L); // 设置一个不存在的关联ID
}
}
@@ -628,7 +670,7 @@ public class StglMemberServiceImpl implements IStglMemberService {
// 查询用户作为队长的志愿者队伍
StglMemberBo captainBo = new StglMemberBo();
captainBo.setMemberType(2); // 志愿者成员
captainBo.setRoleType("0"); // 队长角色
captainBo.setRoleType("队长"); // 队长角色
List<StglMemberVo> captainRecords = baseMapper.selectMemberWithUserInfo(
captainBo.getMemberType(),
@@ -654,4 +696,37 @@ public class StglMemberServiceImpl implements IStglMemberService {
}
}
/**
* 获取用户作为成员所在的队伍ID列表
*/
private List<Long> getMemberTeamIds(Long userId) {
try {
// 查询用户作为成员的志愿者队伍
StglMemberBo memberBo = new StglMemberBo();
memberBo.setMemberType(2); // 志愿者成员
List<StglMemberVo> memberRecords = baseMapper.selectMemberWithUserInfo(
memberBo.getMemberType(),
null, // relationId 不限制
null, // studentNo
null, // studentName
null, // roleType 不限制角色
null, // status
null, // clubName
null, // teamName
userId, // userId 权限过滤
null // params
);
return memberRecords.stream()
.map(StglMemberVo::getRelationId)
.filter(relationId -> relationId != null)
.distinct()
.collect(Collectors.toList());
} catch (Exception e) {
return new ArrayList<>();
}
}
}
@@ -20,6 +20,8 @@ import org.dromara.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
@@ -60,10 +62,10 @@ public class StglMyServiceImpl implements IStglMyService {
* 查询我报名的活动列表(带评分状态)
*/
@Override
public List<MyActivityVo> queryMyActivities() {
public List<MyActivityVo> queryMyActivities(String activityName, String activityType, String isRated) {
Long userId = LoginHelper.getUserId();
String tenantId = LoginHelper.getTenantId();
return stglMyMapper.selectMyActivities(userId, tenantId);
return stglMyMapper.selectMyActivities(userId, tenantId, activityName, activityType, isRated);
}
/**
@@ -106,9 +108,10 @@ public class StglMyServiceImpl implements IStglMyService {
rating.setStudentNo(userInfo.getUserName()); // 使用用户名作为学号
rating.setStudentName(userInfo.getNickName());
// 计算综合评分(三项评分平均值)
double avgScore = (ratingBo.getContentScore() + ratingBo.getOrganizationScore() + ratingBo.getExperienceScore()) / 3.0;
rating.setRatingScore((int) Math.round(avgScore));
// 计算综合评分(三项评分平均值,保留1位小数)
BigDecimal avgScore = BigDecimal.valueOf(ratingBo.getContentScore() + ratingBo.getOrganizationScore() + ratingBo.getExperienceScore())
.divide(BigDecimal.valueOf(3), 1, RoundingMode.HALF_UP);
rating.setRatingScore(avgScore);
rating.setRatingTime(LocalDateTime.now());
return stglActivityRatingMapper.insert(rating) > 0;
@@ -123,7 +126,7 @@ public class StglMyServiceImpl implements IStglMyService {
String tenantId = LoginHelper.getTenantId();
// 查询用户的活动信息
List<MyActivityVo> activities = stglMyMapper.selectMyActivities(userId, tenantId);
List<MyActivityVo> activities = stglMyMapper.selectMyActivities(userId, tenantId, null, null, null);
// 查找指定的活动
return activities.stream()
@@ -22,8 +22,10 @@ import org.dromara.xg.mapper.XgStudentMsgMapper;
import org.dromara.xg.domain.vo.XgStudentMsgVo;
import org.dromara.xg.domain.XgStudentMsg;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.mapper.SysUserRoleMapper;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserRole;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.stgl.utils.AdvisorRoleAssigner;
import cn.dev33.satoken.stp.StpUtil;
@@ -35,6 +37,11 @@ import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.ArrayList;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.type.TypeReference;
import org.dromara.common.json.utils.JsonUtils;
/**
* 志愿者队伍Service业务层处理
@@ -51,8 +58,19 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
private final StglMemberMapper memberMapper;
private final XgStudentMsgMapper studentMsgMapper;
private final SysUserMapper userMapper;
private final SysUserRoleMapper sysUserRoleMapper;
private final AdvisorRoleAssigner advisorRoleAssigner;
/**
* 志愿者队长角色ID
*/
private static final Long VOLUNTEER_CAPTAIN_ROLE_ID = 1957353206166118402L;
/**
* 指导老师角色ID
*/
private static final Long ADVISOR_ROLE_ID = 1959880215953952769L;
/**
* 查询志愿者队伍
*/
@@ -153,6 +171,8 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
bo.setId(add.getId());
// 自动创建队长的成员记录
createLeaderMemberRecord(add);
// 为队长分配角色
assignLeaderRole(add);
// 为指导老师分配角色
assignAdvisorRole(add);
}
@@ -168,7 +188,7 @@ 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());
@@ -180,6 +200,8 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
if (updateResult) {
// 同步更新队长的成员记录
syncLeaderInMembers(update);
// 处理队长角色分配
handleLeaderRoleAssignment(oldTeam, update);
// 处理指导老师角色分配
handleAdvisorRoleAssignment(oldTeam, update);
}
@@ -318,7 +340,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, "队长"); // 队长角色
query.eq(StglMember::getStatus, 2); // 已加入状态
return memberMapper.selectCount(query) > 0;
@@ -448,7 +470,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("队员"); // 队员角色 - 直接写入字符"队员"
member.setStatus(0); // 0-待审核
member.setJoinTime(new Date());
@@ -555,7 +577,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(team.getCreateTime() != null ? team.getCreateTime() : new Date());
leader.setStatus(2); // 已加入状态
leader.setRemark("补充缺失的队长成员记录");
@@ -599,6 +621,9 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
throw new RuntimeException("志愿者队伍不存在");
}
// 保存原队长用户ID,用于角色分配处理
Long oldLeaderUserId = team.getLeaderUserId();
// 2. 获取新队长的学生信息
XgStudentMsg newLeaderStudent = studentMsgMapper.selectOne(
Wrappers.<XgStudentMsg>lambdaQuery()
@@ -633,23 +658,43 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
throw new RuntimeException("更新队伍信息失败");
}
// 5. 更新成员表
// 5. 处理角色分配:移除原队长角色,为新队长分配角色
try {
// 5.1 移除原队长的角色
if (oldLeaderUserId != null) {
removeLeaderRole(oldLeaderUserId);
log.info("志愿者队伍转让:成功移除原队长角色,用户ID: {}, 队伍: {}", oldLeaderUserId, team.getTeamName());
}
// 5.2 为新队长分配角色
StglVolunteerTeam updatedTeam = new StglVolunteerTeam();
updatedTeam.setId(teamId);
updatedTeam.setTeamName(team.getTeamName());
updatedTeam.setLeaderUserId(newLeaderUserId);
assignLeaderRole(updatedTeam);
log.info("志愿者队伍转让:成功为新队长分配角色,用户ID: {}, 队伍: {}", newLeaderUserId, team.getTeamName());
} catch (Exception e) {
log.error("志愿者队伍转让时角色分配出现异常,队伍: {}", team.getTeamName(), e);
// 注意:这里不抛出异常,避免影响转让主流程
}
// 6. 更新成员表
Long currentUserId = LoginHelper.getUserId();
// 5.1 查询原队长在成员表中的记录
// 6.1 查询原队长在成员表中的记录
StglMember oldLeaderMember = null;
if (currentUserId != null) {
oldLeaderMember = memberMapper.selectOne(
Wrappers.<StglMember>lambdaQuery()
.eq(StglMember::getMemberType, 2) // 志愿者队伍成员
.eq(StglMember::getRelationId, teamId)
.eq(StglMember::getRoleType, 0) // 队长角色
.eq(StglMember::getRoleType, "队长") // 队长角色 - 直接使用字符"队长"
.eq(StglMember::getUserId, currentUserId) // 添加当前用户ID条件
.eq(StglMember::getStatus, 2) // 已加入状态
);
}
// 5.2 查询新队长在成员表中的记录
// 6.2 查询新队长在成员表中的记录
StglMember newLeaderMember = memberMapper.selectOne(
Wrappers.<StglMember>lambdaQuery()
.eq(StglMember::getMemberType, 2) // 志愿者队伍成员
@@ -657,7 +702,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
.eq(StglMember::getUserId, newLeaderUserId)
);
// 5.3 更新原队长的成员状态为已退出
// 6.3 更新原队长的成员状态为已退出
if (oldLeaderMember != null) {
StglMember updateOldLeader = new StglMember();
updateOldLeader.setId(oldLeaderMember.getId());
@@ -667,12 +712,12 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
memberMapper.updateById(updateOldLeader);
}
// 5.4 添加或更新新队长的成员记录
// 6.4 添加或更新新队长的成员记录
if (newLeaderMember != null) {
// 如果新队长已经是成员,更新角色和状态
StglMember updateNewLeader = new StglMember();
updateNewLeader.setId(newLeaderMember.getId());
updateNewLeader.setRoleType("0"); // 队长角色
updateNewLeader.setRoleType("队长"); // 队长角色 - 直接写入字符"队长"
updateNewLeader.setStatus(2); // 已加入状态
updateNewLeader.setJoinTime(new Date());
updateNewLeader.setUpdateBy(LoginHelper.getUserId());
@@ -690,7 +735,7 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
newMember.setUserId(newLeaderUserId);
newMember.setStudentNo(newLeaderStudent.getStudentNo());
newMember.setStudentName(newLeaderStudent.getName());
newMember.setRoleType("0"); // 队长角色
newMember.setRoleType("队长"); // 队长角色 - 直接写入字符"队长"
newMember.setJoinTime(new Date());
newMember.setStatus(2); // 已加入状态
newMember.setCreateBy(LoginHelper.getUserId());
@@ -854,10 +899,12 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
*/
private void assignAdvisorRole(StglVolunteerTeam team) {
try {
Long advisorUserId = extractAdvisorUserId(team);
if (advisorUserId != null) {
advisorRoleAssigner.assignAdvisorRole(advisorUserId);
log.info("成功为志愿者队伍 {} 的指导老师分配角色,指导老师用户ID: {}", team.getTeamName(), advisorUserId);
List<Long> advisorUserIds = extractAdvisorUserIds(team);
for (Long advisorUserId : advisorUserIds) {
if (advisorUserId != null) {
advisorRoleAssigner.assignAdvisorRole(advisorUserId);
log.info("成功为志愿者队伍 {} 的指导老师分配角色,指导老师用户ID: {}", team.getTeamName(), advisorUserId);
}
}
} catch (Exception e) {
log.error("为志愿者队伍 {} 的指导老师分配角色时发生异常", team.getTeamName(), e);
@@ -873,23 +920,30 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
*/
private void handleAdvisorRoleAssignment(StglVolunteerTeam oldTeam, StglVolunteerTeam newTeam) {
try {
// 获取更新前后的指导老师用户ID
Long oldAdvisorUserId = oldTeam != null ? extractAdvisorUserId(oldTeam) : null;
Long newAdvisorUserId = extractAdvisorUserId(newTeam);
// 获取更新前后的指导老师用户ID列表
List<Long> oldAdvisorUserIds = oldTeam != null ? extractAdvisorUserIds(oldTeam) : new ArrayList<>();
List<Long> newAdvisorUserIds = extractAdvisorUserIds(newTeam);
// 如果指导老师发生变化
if (!Objects.equals(oldAdvisorUserId, newAdvisorUserId)) {
// 移除旧指导老师的角色
if (oldAdvisorUserId != null) {
advisorRoleAssigner.removeAdvisorRole(oldAdvisorUserId);
log.info("志愿者队伍 {} 移除指导老师,成功移除角色,用户ID: {}", newTeam.getTeamName(), oldAdvisorUserId);
}
// 找出需要移除角色的指导老师
List<Long> removedAdvisorUserIds = oldAdvisorUserIds.stream()
.filter(oldId -> !newAdvisorUserIds.contains(oldId))
.collect(Collectors.toList());
// 为新指导老师分配角色
if (newAdvisorUserId != null) {
advisorRoleAssigner.assignAdvisorRole(newAdvisorUserId);
log.info("志愿者队伍 {} 新增指导老师,成功分配角色,用户ID: {}", newTeam.getTeamName(), newAdvisorUserId);
}
// 找出需要分配角色的指导老师
List<Long> addedAdvisorUserIds = newAdvisorUserIds.stream()
.filter(newId -> !oldAdvisorUserIds.contains(newId))
.collect(Collectors.toList());
// 移除旧指导老师的角色
for (Long advisorUserId : removedAdvisorUserIds) {
advisorRoleAssigner.removeAdvisorRole(advisorUserId);
log.info("志愿者队伍 {} 移除指导老师,成功移除角色,用户ID: {}", newTeam.getTeamName(), advisorUserId);
}
// 为新指导老师分配角色
for (Long advisorUserId : addedAdvisorUserIds) {
advisorRoleAssigner.assignAdvisorRole(advisorUserId);
log.info("志愿者队伍 {} 新增指导老师,成功分配角色,用户ID: {}", newTeam.getTeamName(), advisorUserId);
}
} catch (Exception e) {
log.error("处理志愿者队伍 {} 的指导老师角色分配时发生异常", newTeam.getTeamName(), e);
@@ -897,26 +951,175 @@ public class StglVolunteerTeamServiceImpl implements IStglVolunteerTeamService {
}
}
/**
* 为队长分配角色
*
* @param team 志愿者队伍信息
*/
private void assignLeaderRole(StglVolunteerTeam team) {
try {
if (team.getLeaderUserId() != null) {
// 检查用户是否已有该角色
if (!hasUserRole(team.getLeaderUserId(), VOLUNTEER_CAPTAIN_ROLE_ID)) {
SysUserRole userRole = new SysUserRole();
userRole.setUserId(team.getLeaderUserId());
userRole.setRoleId(VOLUNTEER_CAPTAIN_ROLE_ID);
int result = sysUserRoleMapper.insert(userRole);
if (result > 0) {
log.info("成功为志愿者队伍 {} 的队长分配角色,队长用户ID: {}, 角色ID: {}",
team.getTeamName(), team.getLeaderUserId(), VOLUNTEER_CAPTAIN_ROLE_ID);
} else {
log.error("为志愿者队伍 {} 的队长分配角色失败,队长用户ID: {}", team.getTeamName(), team.getLeaderUserId());
}
} else {
log.debug("志愿者队伍 {} 的队长已有该角色,跳过分配", team.getTeamName());
}
} else {
log.warn("志愿者队伍 {} 的队长用户ID为空,跳过角色分配", team.getTeamName());
}
} catch (Exception e) {
log.error("为志愿者队伍 {} 的队长分配角色时发生异常", team.getTeamName(), e);
// 不抛出异常,避免影响主业务流程
}
}
/**
* 处理队长角色分配(更新时使用)
*
* @param oldTeam 更新前的队伍信息
* @param newTeam 更新后的队伍信息
*/
private void handleLeaderRoleAssignment(StglVolunteerTeam oldTeam, StglVolunteerTeam newTeam) {
try {
// 获取更新前后的队长用户ID
Long oldLeaderUserId = oldTeam != null ? oldTeam.getLeaderUserId() : null;
Long newLeaderUserId = newTeam.getLeaderUserId();
// 如果队长发生变化
if (!Objects.equals(oldLeaderUserId, newLeaderUserId)) {
// 移除旧队长的角色
if (oldLeaderUserId != null) {
removeLeaderRole(oldLeaderUserId);
log.info("志愿者队伍 {} 更换队长,成功移除原队长角色,用户ID: {}", newTeam.getTeamName(), oldLeaderUserId);
}
// 为新队长分配角色
if (newLeaderUserId != null) {
assignLeaderRole(newTeam);
}
}
} catch (Exception e) {
log.error("处理志愿者队伍 {} 的队长角色分配时发生异常", newTeam.getTeamName(), e);
// 不抛出异常,避免影响主业务流程
}
}
/**
* 移除队长角色
*
* @param leaderUserId 队长用户ID
*/
private void removeLeaderRole(Long leaderUserId) {
try {
int result = sysUserRoleMapper.delete(
Wrappers.<SysUserRole>lambdaQuery()
.eq(SysUserRole::getUserId, leaderUserId)
.eq(SysUserRole::getRoleId, VOLUNTEER_CAPTAIN_ROLE_ID)
);
if (result > 0) {
log.info("成功移除用户 {} 的志愿者队长角色", leaderUserId);
} else {
log.debug("用户 {} 没有志愿者队长角色需要移除", leaderUserId);
}
} catch (Exception e) {
log.error("移除用户 {} 的志愿者队长角色时发生异常", leaderUserId, e);
throw new RuntimeException("移除志愿者队长角色失败", e);
}
}
/**
* 检查用户是否已有指定角色
*
* @param userId 用户ID
* @param roleId 角色ID
* @return 是否已有该角色
*/
private boolean hasUserRole(Long userId, Long roleId) {
try {
LambdaQueryWrapper<SysUserRole> query = Wrappers.lambdaQuery();
query.eq(SysUserRole::getUserId, userId)
.eq(SysUserRole::getRoleId, roleId);
return sysUserRoleMapper.selectCount(query) > 0;
} catch (Exception e) {
log.error("检查用户角色关系时发生异常,用户ID: {}, 角色ID: {}", userId, roleId, e);
// 如果查询失败,假设用户没有该角色,继续分配
return false;
}
}
/**
* 从志愿者队伍信息中提取指导老师用户ID
*
* @param team 志愿者队伍信息
* @return 指导老师用户ID列表
*/
private List<Long> extractAdvisorUserIds(StglVolunteerTeam team) {
List<Long> advisorUserIds = new ArrayList<>();
// 1. 从advisorsJson字段提取指导老师用户ID
if (StringUtils.isNotBlank(team.getAdvisorsJson())) {
try {
List<Map<String, Object>> advisors = JsonUtils.parseObject(team.getAdvisorsJson(), new TypeReference<List<Map<String, Object>>>() {});
if (advisors != null) {
for (Map<String, Object> advisor : advisors) {
Object userIdObj = advisor.get("userId");
if (userIdObj != null) {
Long userId = Long.valueOf(userIdObj.toString());
advisorUserIds.add(userId);
}
}
}
} catch (Exception e) {
log.error("解析志愿者队伍 {} 的指导老师JSON数据时发生异常", team.getTeamName(), e);
}
}
// 2. 从advisorName字段提取指导老师用户ID(兼容旧数据)
if (advisorUserIds.isEmpty() && StringUtils.isNotBlank(team.getAdvisorName())) {
try {
// 根据指导老师姓名查找用户ID
LambdaQueryWrapper<SysUser> query = Wrappers.lambdaQuery();
query.eq(SysUser::getNickName, team.getAdvisorName())
.eq(SysUser::getDelFlag, "0")
.eq(SysUser::getStatus, "0")
.last("LIMIT 1");
SysUser advisor = userMapper.selectOne(query);
if (advisor != null) {
log.debug("找到志愿者队伍 {} 的指导老师用户ID: {} ({})", team.getTeamName(), advisor.getUserId(), team.getAdvisorName());
advisorUserIds.add(advisor.getUserId());
} else {
log.debug("未找到志愿者队伍 {} 指导老师的用户信息: {}", team.getTeamName(), team.getAdvisorName());
}
} catch (Exception e) {
log.error("查找志愿者队伍 {} 指导老师用户ID时发生异常", team.getTeamName(), e);
}
}
return advisorUserIds;
}
/**
* 从志愿者队伍信息中提取指导老师用户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;
List<Long> advisorUserIds = extractAdvisorUserIds(team);
return advisorUserIds.isEmpty() ? null : advisorUserIds.get(0);
}
}
@@ -64,4 +64,32 @@
</where>
</select>
<!-- 查询活动评分详情(关联用户表获取详细信息) -->
<select id="selectActivityRatingsWithUserInfo" resultType="org.dromara.stgl.domain.vo.ActivityRatingVo">
SELECT
sar.id,
sar.activity_id as activityId,
sar.user_id as userId,
COALESCE(sar.student_name, su.nick_name, su.user_name) as userName,
sar.student_no as studentNo,
su.phonenumber as phoneNumber,
sd.dept_name as deptName,
su.remark as majorName,
'' as className,
sar.rating_score as ratingScore,
sar.content_score as contentScore,
sar.organization_score as organizationScore,
sar.experience_score as experienceScore,
sar.rating_comment as ratingComment,
sar.rating_time as ratingTime
FROM stgl_activity_rating sar
LEFT JOIN sys_user su ON sar.user_id = su.user_id AND su.del_flag = '0'
LEFT JOIN sys_dept sd ON su.dept_id = sd.dept_id AND sd.del_flag = '0'
<where>
sar.activity_id = #{activityId}
AND sar.deleted = 0
</where>
ORDER BY sar.rating_time DESC
</select>
</mapper>
@@ -200,6 +200,10 @@
<if test="userId != null">
AND m.user_id = #{userId}
</if>
<!-- 联系方式过滤:通过用户表的phonenumber字段 -->
<if test="params != null and params.phone != null and params.phone != ''">
AND u.phonenumber LIKE CONCAT('%', #{params.phone}, '%')
</if>
ORDER BY m.role_type ASC, m.join_time DESC
</select>
@@ -132,6 +132,7 @@
a.update_time,
ar.registration_time as my_registration_time,
CAST(ar.approval_status AS CHAR) as my_registration_status,
CAST(ar.registration_type AS CHAR) as registration_type,
CASE WHEN rat.id IS NOT NULL THEN 1 ELSE 0 END as my_rating_status,
rat.rating_score as my_rating_score,
rat.rating_time as my_rating_time,
@@ -149,15 +150,107 @@
</sql>
<select id="selectMyActivities" resultType="org.dromara.stgl.domain.vo.MyActivityVo">
<include refid="selectMyActivitiesVo"/>
SELECT DISTINCT
a.id,
a.activity_name,
CAST(a.activity_type AS CHAR) as activity_type,
a.activity_theme,
a.start_time,
a.end_time,
a.location,
a.organizer_name,
CAST(a.related_type AS CHAR) as related_type,
CASE
WHEN a.related_type = 1 THEN c.club_name
WHEN a.related_type = 2 THEN vt.team_name
ELSE NULL
END as organization_name,
a.instructors,
CAST(a.activity_status AS CHAR) as activity_status,
-- 动态计算报名状态:优先根据活动状态,再根据报名时间范围
CAST(
CASE
-- 首先根据活动状态强制设置(优先级最高)
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
<![CDATA[WHEN NOW() < a.registration_start THEN '0']]>
<![CDATA[WHEN NOW() >= a.registration_start AND NOW() <= a.registration_end THEN '1']]>
<![CDATA[WHEN NOW() > a.registration_end THEN '2']]>
ELSE a.registration_status
END
-- 其他情况保持原状态
ELSE a.registration_status
END AS CHAR
) as registration_status,
a.poster_url,
a.description,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
COALESCE(direct_ar.registration_time, team_ar.registration_time) as my_registration_time,
CAST(COALESCE(direct_ar.approval_status, team_ar.approval_status) AS CHAR) as my_registration_status,
CAST(COALESCE(direct_ar.registration_type, team_ar.registration_type) AS CHAR) as registration_type,
CASE WHEN rat.id IS NOT NULL THEN 1 ELSE 0 END as my_rating_status,
rat.rating_score as my_rating_score,
rat.rating_time as my_rating_time,
(SELECT AVG(rating_score) FROM stgl_activity_rating WHERE activity_id = a.id AND deleted = 0) as average_rating,
CASE
WHEN rat.id IS NOT NULL THEN 0
WHEN a.activity_status IN ('4', '5') AND COALESCE(direct_ar.approval_status, team_ar.approval_status) = '1' THEN 1
ELSE 0
END as can_rate
FROM stgl_activity a
LEFT JOIN (
-- 直接报名的活动(个人报名或作为队长的团队报名)
SELECT ar.* FROM stgl_activity_registration ar
WHERE ar.user_id = #{userId} AND ar.deleted = 0 AND ar.tenant_id = #{tenantId}
) direct_ar ON a.id = direct_ar.activity_id
LEFT JOIN (
-- 作为团队成员参与的活动
SELECT ar.activity_id, ar.registration_time, ar.approval_status, ar.registration_type
FROM stgl_activity_registration ar
INNER JOIN stgl_activity_team_info ati ON ar.team_id = ati.id
WHERE JSON_SEARCH(ati.team_members, 'one', #{userId}, NULL, '$[*].userId') IS NOT NULL
AND ar.deleted = 0
AND ati.deleted = 0
AND ar.tenant_id = #{tenantId}
AND ati.tenant_id = #{tenantId}
AND ar.approval_status = '1' -- 只显示已通过的团队报名
) team_ar ON a.id = team_ar.activity_id
LEFT JOIN stgl_club c ON a.related_type = 1 AND a.related_club_id = c.id AND c.deleted = 0 AND c.tenant_id = #{tenantId}
LEFT JOIN stgl_volunteer_team vt ON a.related_type = 2 AND a.related_club_id = vt.id AND vt.deleted = 0 AND vt.tenant_id = #{tenantId}
LEFT JOIN stgl_activity_rating rat ON a.id = rat.activity_id AND rat.user_id = #{userId} AND rat.deleted = 0
<where>
ar.user_id = #{userId}
AND ar.deleted = 0
(direct_ar.activity_id IS NOT NULL OR team_ar.activity_id IS NOT NULL)
AND a.deleted = 0
AND a.tenant_id = #{tenantId}
AND ar.tenant_id = #{tenantId}
<if test="activityName != null and activityName != ''">
AND a.activity_name LIKE CONCAT('%', #{activityName}, '%')
</if>
<if test="activityType != null and activityType != ''">
AND a.activity_type = #{activityType}
</if>
<if test="isRated != null and isRated != ''">
<if test="isRated == '1'">
AND rat.id IS NOT NULL
</if>
<if test="isRated == '0'">
AND rat.id IS NULL
</if>
</if>
</where>
ORDER BY ar.registration_time DESC
ORDER BY COALESCE(direct_ar.registration_time, team_ar.registration_time) DESC
</select>
<!-- 我的报名记录查询(统一查询社团+志愿团队+活动) -->
@@ -14,12 +14,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="teamMembers" column="team_members" />
<result property="teamSize" column="team_size" />
<result property="description" column="description" />
<result property="leaderGender" column="leader_gender" />
<result property="leaderPhone" column="leader_phone" />
<result property="leaderEmail" column="leader_email" />
<result property="leaderDepartment" column="leader_department" />
<result property="leaderMajor" column="leader_major" />
<result property="leaderClassName" column="leader_class_name" />
<result property="tenantId" column="tenant_id" />
<result property="createDept" column="create_dept" />
<result property="createBy" column="create_by" />
@@ -28,16 +22,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time" />
<result property="deleted" column="deleted" />
<result property="activityName" column="activity_name" />
<!-- 队长详细信息字段 -->
<result property="leaderGender" column="leader_gender" />
<result property="leaderPhone" column="leader_phone" />
<result property="leaderEmail" column="leader_email" />
<result property="leaderDepartment" column="leader_department" />
<result property="leaderMajor" column="leader_major" />
<result property="leaderClassName" column="leader_class_name" />
</resultMap>
<sql id="selectStglActivityTeamInfoVo">
select t.id, t.team_name, t.activity_id, t.leader_user_id, t.leader_name, t.leader_student_no,
t.team_members, t.team_size, t.description, t.leader_gender, t.leader_phone, t.leader_email,
t.leader_department, t.leader_major, t.leader_class_name,
t.team_members, t.team_size, t.description,
t.tenant_id, t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time, t.deleted,
a.activity_name
a.activity_name,
<!-- 队长详细信息 -->
s.gender as leader_gender,
s.phone as leader_phone,
s.email as leader_email,
s.college_name as leader_department,
s.major_name as leader_major,
s.class_name as leader_class_name
from stgl_activity_team_info t
left join stgl_activity a on t.activity_id = a.id
left join xg_student_msg s on t.leader_student_no = s.student_no and s.deleted = 0
</sql>
<select id="selectList" parameterType="org.dromara.stgl.domain.StglActivityTeamInfo" resultMap="StglActivityTeamInfoResult">
@@ -66,4 +74,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by t.create_time desc
</select>
<!-- 根据条件查询团队信息列表(VO对象) -->
<select id="selectVoList" resultMap="StglActivityTeamInfoResult">
<include refid="selectStglActivityTeamInfoVo"/>
<where>
t.deleted = 0
<if test="ew != null and ew.sqlSegment != null and ew.sqlSegment != ''">
and (${ew.sqlSegment})
</if>
</where>
order by t.create_time desc
</select>
<!-- 根据活动ID查询团队列表 -->
<select id="selectVoListByActivityId" parameterType="Long" resultMap="StglActivityTeamInfoResult">
<include refid="selectStglActivityTeamInfoVo"/>
<where>
t.deleted = 0
and t.activity_id = #{activityId}
</where>
order by t.create_time desc
</select>
</mapper>
@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.stgl.mapper.StglClassMapper">
<resultMap type="org.dromara.stgl.domain.vo.StglClassVo" id="StglClassResult">
<result property="id" column="id"/>
<result property="studentNo" column="student_no"/>
<result property="studentName" column="name"/>
<result property="gender" column="gender"/>
<result property="phone" column="phone"/>
<result property="className" column="class_name"/>
<result property="clubCount" column="club_count"/>
<result property="volunteerTeamCount" column="volunteer_team_count"/>
<result property="activityCount" column="activity_count"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="tenantId" column="tenant_id"/>
<result property="version" column="version"/>
<result property="deleted" column="deleted"/>
</resultMap>
<!-- 查询班主任的班级列表 -->
<select id="selectTeacherClasses" parameterType="Long" resultType="java.util.Map">
SELECT DISTINCT
c.id,
c.class_name as className,
c.college_name as collegeName,
c.major_name as majorName,
c.grade
FROM xg_class_msg c
INNER JOIN xg_class_teacher_counselor_rel tcr ON c.id = tcr.class_id
WHERE tcr.teacher_id = #{userId}
AND c.deleted = 0
AND tcr.deleted = 0
AND tcr.teacher_type = 'class_teacher'
AND (tcr.end_date IS NULL OR tcr.end_date > NOW())
ORDER BY c.grade DESC, c.class_name ASC
</select>
<!-- 查询班级学生列表(包含社团、志愿者队伍、活动统计) -->
<select id="selectClassStudents" parameterType="java.util.Map" resultMap="StglClassResult">
SELECT
s.id,
s.student_no,
s.name,
s.gender,
s.phone,
c.class_name,
COALESCE(club_stats.club_count, 0) as club_count,
COALESCE(volunteer_stats.volunteer_team_count, 0) as volunteer_team_count,
COALESCE(activity_stats.activity_count, 0) as activity_count,
s.create_by,
s.create_time,
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
LEFT JOIN (
SELECT
m.user_id,
COUNT(DISTINCT m.relation_id) as club_count
FROM stgl_member m
WHERE m.member_type = 1
AND m.deleted = 0
AND m.status = 1
GROUP BY m.user_id
) club_stats ON s.id = club_stats.user_id
LEFT JOIN (
SELECT
m.user_id,
COUNT(DISTINCT m.relation_id) as volunteer_team_count
FROM stgl_member m
WHERE m.member_type = 2
AND m.deleted = 0
AND m.status = 1
GROUP BY m.user_id
) volunteer_stats ON s.id = volunteer_stats.user_id
LEFT JOIN (
SELECT
ar.user_id,
COUNT(DISTINCT ar.activity_id) as activity_count
FROM stgl_activity_registration ar
WHERE ar.deleted = 0
AND ar.approval_status = 1
GROUP BY ar.user_id
) activity_stats ON s.id = activity_stats.user_id
<where>
s.deleted = 0
AND s.student_status = '1'
<if test="classId != null and classId != ''">
AND s.class_id = #{classId}
</if>
<if test="studentName != null and studentName != ''">
AND s.name LIKE CONCAT('%', #{studentName}, '%')
</if>
<if test="studentNo != null and studentNo != ''">
AND s.student_no LIKE CONCAT('%', #{studentNo}, '%')
</if>
</where>
ORDER BY s.student_no ASC
<if test="offset != null and pageSize != null">
LIMIT #{pageSize} OFFSET #{offset}
</if>
</select>
<!-- 查询班级学生总数 -->
<select id="selectClassStudentsCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM xg_student_msg s
<where>
s.deleted = 0
AND s.student_status = '1'
<if test="classId != null and classId != ''">
AND s.class_id = #{classId}
</if>
<if test="studentName != null and studentName != ''">
AND s.name LIKE CONCAT('%', #{studentName}, '%')
</if>
<if test="studentNo != null and studentNo != ''">
AND s.student_no LIKE CONCAT('%', #{studentNo}, '%')
</if>
</where>
</select>
<!-- 查询学生社团详情 -->
<select id="selectStudentClubs" parameterType="Long" resultType="java.util.Map">
SELECT
c.id,
c.club_name as clubName,
c.club_type as clubType,
DATE_FORMAT(c.establish_date, '%Y-%m-%d') as establishDate,
c.member_limit as memberLimit,
c.president_name as presidentName,
c.president_phone as presidentPhone,
c.president_dept as presidentDept,
c.president_major as presidentMajor,
c.president_class as presidentClass,
c.advisor_name as advisorName,
c.advisor_dept as advisorDept,
c.advisor_phone as advisorPhone
FROM stgl_club c
INNER JOIN stgl_member m ON c.id = m.relation_id
WHERE m.user_id = #{studentId}
AND m.member_type = 1
AND m.deleted = 0
AND m.status = 1
AND c.deleted = 0
AND c.status = 1
ORDER BY c.create_time DESC
</select>
<!-- 查询学生志愿者队伍详情 -->
<select id="selectStudentVolunteerTeams" parameterType="Long" resultType="java.util.Map">
SELECT
vt.id,
vt.team_name as teamName,
DATE_FORMAT(vt.establish_date, '%Y-%m-%d') as establishDate,
vt.leader_name as leaderName,
vt.leader_phone as leaderPhone,
vt.leader_dept as leaderDept,
vt.leader_major as leaderMajor,
vt.leader_class as leaderClass,
vt.advisor_name as advisorName,
vt.advisor_dept as advisorDept,
vt.advisor_phone as advisorPhone
FROM stgl_volunteer_team vt
INNER JOIN stgl_member m ON vt.id = m.relation_id
WHERE m.user_id = #{studentId}
AND m.member_type = 2
AND m.deleted = 0
AND m.status = 1
AND vt.deleted = 0
AND vt.status = 1
ORDER BY vt.create_time DESC
</select>
<!-- 查询学生活动详情 -->
<select id="selectStudentActivities" parameterType="Long" resultType="java.util.Map">
SELECT DISTINCT
a.id,
a.activity_name as activityName,
a.activity_type as activityType,
a.activity_theme as activityTheme,
a.location,
CONCAT(
DATE_FORMAT(a.start_time, '%Y-%m-%d %H:%i'),
' 至 ',
DATE_FORMAT(a.end_time, '%Y-%m-%d %H:%i')
) as activityTime,
CASE
WHEN a.related_type = 1 THEN c.club_name
WHEN a.related_type = 2 THEN vt.team_name
ELSE '无'
END as relatedOrganization,
CASE
WHEN a.related_type = 1 THEN c.advisor_name
WHEN a.related_type = 2 THEN vt.advisor_name
ELSE '无'
END as advisorName,
CASE
WHEN a.related_type = 1 THEN c.advisor_dept
WHEN a.related_type = 2 THEN vt.advisor_dept
ELSE '无'
END as advisorDept,
CASE
WHEN a.related_type = 1 THEN c.advisor_phone
WHEN a.related_type = 2 THEN vt.advisor_phone
ELSE '无'
END as advisorPhone
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
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
)
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)), '$[*]')
)
)
ORDER BY a.start_time DESC
</select>
</mapper>
@@ -0,0 +1,33 @@
-- 班主任查看本班学生社团、志愿者队伍、活动参加情况权限配置
-- 执行时间:2025-01-15
-- 1. 添加菜单权限
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
VALUES (2000001, '班级学生参与情况', 2000, 1, 'stclass', 'stgl/stclass/index', NULL, 1, 0, 'C', '0', '0', 'stgl:stclass:list', 'education', 103, 1, NOW(), 1, NOW(), '班主任查看本班学生社团、志愿者队伍、活动参加情况');
-- 2. 添加按钮权限
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
VALUES (2000002, '班级学生参与情况查询', 2000001, 1, '', '', NULL, 1, 0, 'F', '0', '0', 'stgl:stclass:query', '#', 103, 1, NOW(), 1, NOW(), '班级学生参与情况查询');
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
VALUES (2000003, '班级学生参与情况导出', 2000001, 2, '', '', NULL, 1, 0, 'F', '0', '0', 'stgl:stclass:export', '#', 103, 1, NOW(), 1, NOW(), '班级学生参与情况导出');
-- 3. 为班主任角色(head_teacher)分配权限
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1947639680473493505, 2000001);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1947639680473493505, 2000002);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1947639680473493505, 2000003);
-- 4. 为管理员角色分配权限
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 2000001);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 2000002);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 2000003);
-- 5. 为超级管理员角色分配权限
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 2000001);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 2000002);
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 2000003);
-- 权限字符说明:
-- stgl:stclass:list - 班级学生参与情况列表查询权限
-- stgl:stclass:query - 班级学生参与情况详情查询权限
-- stgl:stclass:export - 班级学生参与情况导出权限