14 KiB
14 KiB
02-组织关系处理
📋 概述
本分文档详细说明学生退学、休学、毕业处理中的组织关系处理内容,包括班级干部信息和社团成员关系的变更逻辑。
👥 组织关系处理
1. 班级干部信息处理
📊 数据库表结构
表名: xg_class_pos_msg
主键: id (bigint(20), 雪花ID)
核心关联字段:
class_id: 班级ID,关联xg_class_msg.idstudent_id: 学生ID,关联xg_student_msg.idstudent_no: 学号student_name: 学生姓名(冗余字段)
🎯 关键业务字段
基于数据库表结构 xg_class_pos_msg,关键字段如下:
| 字段名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
is_current |
tinyint(1) | 是否现任(0-非现任,1-现任) | 1 |
cadre_status |
char(1) | 职务任职状态(关联stu_cadre_status字典) | 1 |
appointment_date |
date | 任职日期 | - |
term_start_date |
date | 任期开始日期 | - |
term_end_date |
date | 任期结束日期 | NULL |
term_duration |
int(11) | 任期时长(月) | 12 |
dismissal_date |
date | 离任日期 | NULL |
dismissal_reason |
varchar(200) | 离任原因 | NULL |
appointment_method |
varchar(20) | 任命方式(appointment/election/recommendation) | appointment |
🎯 干部状态字典
系统使用 stu_cadre_status 字典类型,具体定义如下:
| 状态值 | 状态名称 | 说明 | 样式类 |
|---|---|---|---|
1 |
在任 | 正常任职状态 | primary |
2 |
到期 | 任期自然到期 | success |
3 |
辞职 | 干部主动辞职 | warning |
4 |
免职 | 被免去职务 | danger |
5 |
调任 | 职务调整调动 | info |
6 |
休学 | 因学生休学离任 | danger |
关键字段说明 (基于实体类代码分析):
isCurrent: 是否现任 (0-非现任,1-现任)cadreStatus: 学生职务任职状态dismissalDate: 离任日期dismissalReason: 离任原因termStartDate: 任期开始日期termEndDate: 任期结束日期termDuration: 任期时长(月)
🔄 离任业务流程
📋 完整离任流程
1. 验证干部信息存在性和状态
2. 计算任期时长 (term_start_date 到 term_end_date)
3. 更新干部状态为非现任 (is_current = 0)
4. 设置离任状态和原因
5. 更新任期结束日期和离任日期
6. 删除用户角色关联 (sys_user_role)
7. 记录操作日志
💻 后端实现逻辑
控制器接口: POST /xgClassPosMsg/xgClassPosMsg/dismiss/{id}
核心方法: XgClassPosMsgServiceImpl.dismissCadre()
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean dismissCadre(Long id, Date termEndDate, String cadreStatus, String dismissalReason) {
// 1. 查询并验证干部信息
XgClassPosMsg classPosMsg = baseMapper.selectById(id);
// 2. 计算任期时长
Long termDuration = calculateTermDuration(classPosMsg.getTermStartDate(), termEndDate);
// 3. 更新干部信息
XgClassPosMsg updateEntity = new XgClassPosMsg();
updateEntity.setId(id);
updateEntity.setTermEndDate(termEndDate);
updateEntity.setTermDuration(termDuration);
updateEntity.setCadreStatus(cadreStatus);
updateEntity.setDismissalReason(dismissalReason);
updateEntity.setDismissalDate(termEndDate);
updateEntity.setIsCurrent(0L); // 设置为非现任
baseMapper.updateById(updateEntity);
// 4. 删除用户角色关联
sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
.eq(SysUserRole::getUserId, classPosMsg.getStudentId()));
return true;
}
🎨 前端离任界面
文件位置: web/src/views/xg/xsjcxx/xgClassPosMsg/xgClassPosMsg/index.vue
离任按钮: 仅对 is_current = 1 的干部显示
<!-- 离任按钮 -->
<el-tooltip content="离任" placement="top">
<el-button
link
type="warning"
icon="ArrowDown"
@click="handleDismissal(scope.row)"
v-if="scope.row.isCurrent === 1"
></el-button>
</el-tooltip>
<!-- 离任对话框 -->
<el-dialog title="班级干部离任" v-model="dismissalDialog.visible" width="500px" append-to-body>
<el-form ref="dismissalFormRef" :model="dismissalForm" :rules="dismissalRules" label-width="140px">
<!-- 当前信息(只读) -->
<el-form-item label="班级名称" prop="className">
<el-input v-model="dismissalForm.className" disabled />
</el-form-item>
<el-form-item label="学生姓名" prop="studentName">
<el-input v-model="dismissalForm.studentName" disabled />
</el-form-item>
<el-form-item label="任期开始日期" prop="termStartDate">
<el-input v-model="dismissalForm.termStartDate" disabled />
</el-form-item>
<!-- 离任信息(可填写) -->
<el-form-item label="任期结束日期" prop="termEndDate">
<el-date-picker
clearable
v-model="dismissalForm.termEndDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择任期结束日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="离任状态" prop="cadreStatus">
<el-select v-model="dismissalForm.cadreStatus" placeholder="请选择离任状态">
<el-option label="到期" value="2" />
<el-option label="辞职" value="3" />
<el-option label="免职" value="4" />
<el-option label="调任" value="5" />
<el-option label="休学" value="6" />
</el-select>
</el-form-item>
<el-form-item label="离任原因" prop="dismissalReason">
<el-input v-model="dismissalForm.dismissalReason" type="textarea" placeholder="请输入离任原因" />
</el-form-item>
</el-form>
</el-dialog>
🔄 学生状态变更时的干部处理逻辑
- 休学:
cadre_status = '6'(休学),is_current = 0,dismissal_reason = '学生休学' - 退学:
cadre_status = '4'(免职),is_current = 0,dismissal_reason = '学生退学' - 毕业:
cadre_status = '4'(免职),is_current = 0,dismissal_reason = '学生毕业'
💾 SQL批量处理脚本
-- 参数说明:
-- @student_id: 学生ID
-- @change_type: 变更类型 (XIU_XUE-休学, TUI_XUE-退学, BI_YE-毕业)
-- @operator_id: 操作员ID
-- @dismissal_date: 离任日期 (默认为当前日期)
SET @dismissal_date = COALESCE(@dismissal_date, CURDATE());
-- 1. 更新干部状态(休学)
UPDATE xg_class_pos_msg
SET is_current = 0,
cadre_status = '6', -- 休学状态
term_end_date = @dismissal_date,
dismissal_date = @dismissal_date,
dismissal_reason = '学生休学',
term_duration = TIMESTAMPDIFF(MONTH, term_start_date, @dismissal_date),
update_by = @operator_id,
update_time = NOW()
WHERE student_id = @student_id
AND is_current = 1
AND deleted = 0
AND @change_type = 'XIU_XUE';
-- 2. 更新干部状态(退学/毕业)
UPDATE xg_class_pos_msg
SET is_current = 0,
cadre_status = '4', -- 免职状态
term_end_date = @dismissal_date,
dismissal_date = @dismissal_date,
dismissal_reason = CASE
WHEN @change_type = 'TUI_XUE' THEN '学生退学'
WHEN @change_type = 'BI_YE' THEN '学生毕业'
ELSE '学生状态变更'
END,
term_duration = TIMESTAMPDIFF(MONTH, term_start_date, @dismissal_date),
update_by = @operator_id,
update_time = NOW()
WHERE student_id = @student_id
AND is_current = 1
AND deleted = 0
AND @change_type IN ('TUI_XUE', 'BI_YE');
2. 社团成员关系处理
📊 数据库表结构
表名: stgl_member (原名 club_member,现已重构)
主键: id (bigint(20))
核心关联字段:
user_id: 用户ID,关联学生用户IDstudent_no: 学号student_name: 学生姓名(冗余字段)relation_id: 关联ID(社团ID或志愿者队伍ID)member_type: 成员类型(1-社团成员,2-志愿者)
🎯 成员状态字典
系统使用 stgl_member_status 字典类型,具体定义如下:
| 状态值 | 状态名称 | 说明 | 样式类 |
|---|---|---|---|
0 |
待审核 | 申请加入,等待审核 | warning |
1 |
审核中 | 正在审核中 | info |
2 |
已加入 | 正式成员 | success |
3 |
已驳回 | 审核未通过 | danger |
4 |
已退出 | 已退出组织 | danger |
关键字段说明 (基于实体类代码分析):
memberType: 成员类型 (1-社团成员,2-志愿者)userId: 用户ID,对应学生IDstudentNo: 学号studentName: 学生姓名roleType: 角色类型 (社长、副社长、部长、普通成员)joinTime: 加入时间status: 状态 (0-待审核,1-审核中,2-已加入,3-已驳回,4-已退出)
🔄 退出处理逻辑
📋 退出业务规则
- 适用范围: 对所有状态为"待审核"(0)、"审核中"(1)、"已加入"(2)的成员
- 处理方式: 将状态更新为"已退出"(4)
- 数据保留: 保留历史记录,不物理删除
- 关联清理: 不涉及其他关联数据的清理
💻 后端实现逻辑
所在模块: ruoyi-stgl (社团管理模块)
实体类: StglMember.java
服务类: StglMemberServiceImpl.java
// 社团成员实体类关键字段
@Data
@TableName("stgl_member")
public class StglMember extends TenantEntity {
private Long userId; // 用户ID
private String studentNo; // 学号
private String studentName; // 学生姓名
private Integer memberType; // 成员类型:1-社团成员,2-志愿者
private Long relationId; // 关联ID
private Integer status; // 状态:0-待审核,1-审核中,2-已加入,3-已驳回,4-已退出
private String roleType; // 角色类型
private Date joinTime; // 加入时间
}
🎨 前端界面展示
管理界面: stgl/member/index.vue
状态显示: 使用字典标签显示成员状态
<!-- 成员状态列 -->
<el-table-column label="状态" align="center" prop="status" width="100">
<template #default="scope">
<dict-tag :options="stgl_member_status" :value="scope.row.status" />
</template>
</el-table-column>
🔄 学生状态变更时的成员处理逻辑
- 休学: 成员状态改为
4(已退出),退出原因为"学生休学" - 退学: 成员状态改为
4(已退出),退出原因为"学生退学" - 毕业: 成员状态改为
4(已退出),退出原因为"学生毕业"
💾 SQL批量处理脚本
-- 参数说明:
-- @student_id: 学生ID (对应user_id)
-- @change_type: 变更类型 (XIU_XUE-休学, TUI_XUE-退学, BI_YE-毕业)
-- @operator_id: 操作员ID
-- 更新社团/志愿者成员状态为已退出
UPDATE stgl_member
SET status = 4, -- 已退出状态
update_by = @operator_id,
update_time = NOW(),
remark = CONCAT(COALESCE(remark, ''), ' | 退出原因:', CASE
WHEN @change_type = 'XIU_XUE' THEN '学生休学'
WHEN @change_type = 'TUI_XUE' THEN '学生退学'
WHEN @change_type = 'BI_YE' THEN '学生毕业'
ELSE '学生状态变更'
END, ' - ', NOW())
WHERE user_id = @student_id
AND status IN (0, 1, 2) -- 待审核、审核中、已加入
AND deleted = 0;
🔗 关联数据处理
1. 用户角色权限清理
📋 角色关联表
表名: sys_user_role
关联逻辑: 当干部离任时,需要清理对应的用户角色关联
🔄 清理逻辑
// 在干部离任时执行角色清理
int deleteCount = sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
.eq(SysUserRole::getUserId, classPosMsg.getStudentId()));
⚠️ 注意事项
- 仅限干部离任: 普通社团成员退出时不清理角色权限
- 角色识别: 根据用户ID清理所有相关角色关联
- 权限回收: 确保干部权限及时回收,避免安全风险
2. 数据一致性保证
🛡️ 事务处理要求
-- 建议在学生状态变更的大事务中包含组织关系处理
START TRANSACTION;
-- 1. 更新学生学籍状态
UPDATE xg_student_msg SET student_status = ? WHERE id = ?;
-- 2. 处理班级干部关系
UPDATE xg_class_pos_msg SET is_current = 0, cadre_status = ? WHERE student_id = ?;
-- 3. 处理社团成员关系
UPDATE stgl_member SET status = 4 WHERE user_id = ?;
-- 4. 清理用户角色(如果需要)
DELETE FROM sys_user_role WHERE user_id = ?;
COMMIT;
📊 处理统计
| 处理类型 | 涉及表数量 | 主要操作 |
|---|---|---|
| 班级干部 | 2 (干部表+角色表) | 更新状态+清理权限 |
| 社团成员 | 1 (成员表) | 更新状态 |
| 总计 | 3个表 | 状态更新+权限清理 |
⚠️ 重要注意事项
1. 业务规则约束
- 干部离任: 必须通过专门的离任接口,计算任期时长
- 成员退出: 直接更新状态,不涉及权限清理
- 数据保留: 所有操作都保留历史记录,便于审计
- 状态验证: 操作前验证当前状态的合法性
2. 权限与安全
- 操作权限: 干部离任需要专门的权限验证
- 角色清理: 确保干部权限及时回收,防止权限泄露
- 审计记录: 记录所有组织关系变更的操作日志
- 数据完整性: 保证关联数据的完整性约束
3. 性能优化建议
- 批量处理: 支持对多个学生的组织关系批量处理
- 索引优化: 确保学生ID相关的查询有适当索引
- 事务控制: 使用合适的事务隔离级别保证数据一致性
- 异步处理: 大批量操作考虑异步处理机制
📅 更新记录
- 2025-12-XX: 分文档创建,包含组织关系处理逻辑
- 2025-12-XX: 基于代码分析完善技术实现细节和业务逻辑
- 后续更新: 根据实际业务需求持续完善
本分文档详细说明学生状态变更时的组织关系处理逻辑和技术实现,包括班级干部职务和社团成员关系的清理。