diff --git a/backend/ruoyi-modules/pangu-business/sql/member_test_data.sql b/backend/ruoyi-modules/pangu-business/sql/member_test_data.sql new file mode 100644 index 0000000..a00f823 --- /dev/null +++ b/backend/ruoyi-modules/pangu-business/sql/member_test_data.sql @@ -0,0 +1,113 @@ +-- ============================================================ +-- 会员测试数据(31条)- 覆盖各种测试场景 +-- 作者:湖北新华业务中台研发团队 +-- 创建时间:2026-02-02 +-- ============================================================ + +USE `pguser-db`; + +-- 清空现有测试数据(可选,谨慎使用) +-- DELETE FROM pg_member WHERE member_id >= 1000; + +-- 密码统一为 123456 的 BCrypt 加密结果 +-- $2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2 + +-- ============================================================ +-- 家长会员(20条)- 测试各种情况 +-- ============================================================ + +-- 1-5: 正常状态家长,不同性别,小程序注册 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1001, 'JS1738400001001', '13800000001', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '张三爸爸', '1', '1985-03-15', '1', '1', '2026-01-15 10:30:00', '0', '000000', 103, 1, NOW(), '0'), +(1002, 'JS1738400001002', '13800000002', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '李四妈妈', '2', '1987-06-20', '1', '1', '2026-01-16 14:20:00', '0', '000000', 103, 1, NOW(), '0'), +(1003, 'JS1738400001003', '13800000003', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '王五家长', '0', NULL, '1', '1', '2026-01-17 09:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1004, 'JS1738400001004', '13800000004', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '赵六爷爷', '1', '1958-12-01', '1', '1', '2026-01-18 16:45:00', '0', '000000', 103, 1, NOW(), '0'), +(1005, 'JS1738400001005', '13800000005', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '钱七奶奶', '2', '1960-08-08', '1', '1', '2026-01-19 11:30:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 6-10: 正常状态家长,H5注册,有微信openId +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, open_id, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1006, 'JS1738400001006', '13800000006', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '孙八爸爸', '1', '1982-04-10', '1', 'oXYZ123456789abc001', '2', '2026-01-20 08:15:00', '0', '000000', 103, 1, NOW(), '0'), +(1007, 'JS1738400001007', '13800000007', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '周九妈妈', '2', '1984-09-25', '1', 'oXYZ123456789abc002', '2', '2026-01-21 13:40:00', '0', '000000', 103, 1, NOW(), '0'), +(1008, 'JS1738400001008', '13800000008', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '吴十家长', '1', '1979-01-30', '1', 'oXYZ123456789abc003', '2', '2026-01-22 17:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1009, 'JS1738400001009', '13800000009', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '郑十一妈妈', '2', NULL, '1', 'oXYZ123456789abc004', '2', '2026-01-23 10:20:00', '0', '000000', 103, 1, NOW(), '0'), +(1010, 'JS1738400001010', '13800000010', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '冯十二爸爸', '1', '1975-07-14', '1', 'oXYZ123456789abc005', '2', '2026-01-24 15:55:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 11-15: 后台新增的家长 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1011, 'JS1738400001011', '13800000011', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '陈十三家长', '1', '1980-11-11', '1', '3', '2026-01-25 09:30:00', '0', '000000', 103, 1, NOW(), '0'), +(1012, 'JS1738400001012', '13800000012', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '楚十四妈妈', '2', '1983-02-28', '1', '3', '2026-01-26 11:15:00', '0', '000000', 103, 1, NOW(), '0'), +(1013, 'JS1738400001013', '13800000013', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '魏十五爸爸', '1', NULL, '1', '3', '2026-01-27 14:40:00', '0', '000000', 103, 1, NOW(), '0'), +(1014, 'JS1738400001014', '13800000014', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '蒋十六家长', '0', NULL, '1', '3', '2026-01-28 16:20:00', '0', '000000', 103, 1, NOW(), '0'), +(1015, 'JS1738400001015', '13800000015', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '沈十七妈妈', '2', '1986-05-05', '1', '3', '2026-01-29 08:00:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 16-18: 批量导入的家长 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1016, 'JS1738400001016', '13800000016', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '韩十八爸爸', '1', '1978-08-18', '1', '4', '2026-01-30 10:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1017, 'JS1738400001017', '13800000017', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '杨十九妈妈', '2', '1981-10-10', '1', '4', '2026-01-30 10:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1018, 'JS1738400001018', '13800000018', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '朱二十家长', '1', NULL, '1', '4', '2026-01-30 10:00:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 19-20: 停用状态的家长 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1019, 'JS1738400001019', '13800000019', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '秦廿一爸爸', '1', '1976-03-03', '1', '1', '2025-12-01 09:00:00', '1', '000000', 103, 1, NOW(), '0'), +(1020, 'JS1738400001020', '13800000020', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '尤廿二妈妈', '2', '1980-06-15', '1', '2', '2025-11-15 14:30:00', '1', '000000', 103, 1, NOW(), '0'); + +-- ============================================================ +-- 教师会员(11条)- 需要学校信息 +-- 假设已有学校数据:school_id=1 为武汉第一中学 +-- ============================================================ + +-- 21-25: 正常状态教师,小程序注册 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, region_id, school_id, school_grade_id, school_class_id, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1021, 'JS1738400001021', '13900000021', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '许老师', '1', '1988-01-20', '2', 420102, 1, 1, 1, '1', '2026-01-10 08:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1022, 'JS1738400001022', '13900000022', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '何老师', '2', '1990-05-15', '2', 420102, 1, 1, 2, '1', '2026-01-11 09:30:00', '0', '000000', 103, 1, NOW(), '0'), +(1023, 'JS1738400001023', '13900000023', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '吕老师', '1', '1985-09-08', '2', 420102, 1, 2, 1, '1', '2026-01-12 10:15:00', '0', '000000', 103, 1, NOW(), '0'), +(1024, 'JS1738400001024', '13900000024', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '施老师', '2', '1992-03-22', '2', 420102, 1, 2, 2, '1', '2026-01-13 11:45:00', '0', '000000', 103, 1, NOW(), '0'), +(1025, 'JS1738400001025', '13900000025', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '张老师', '1', '1983-07-30', '2', 420102, 1, 3, 1, '1', '2026-01-14 13:20:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 26-28: H5注册的教师,有微信openId +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, open_id, region_id, school_id, school_grade_id, school_class_id, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1026, 'JS1738400001026', '13900000026', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '孔老师', '2', '1989-11-11', '2', 'oTEACH123456789001', 420103, 1, 3, 2, '2', '2026-01-15 14:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1027, 'JS1738400001027', '13900000027', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '曹老师', '1', '1987-04-05', '2', 'oTEACH123456789002', 420103, 1, 4, 1, '2', '2026-01-16 15:30:00', '0', '000000', 103, 1, NOW(), '0'), +(1028, 'JS1738400001028', '13900000028', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '严老师', '2', '1991-08-25', '2', 'oTEACH123456789003', 420103, 1, 4, 2, '2', '2026-01-17 16:45:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 29-30: 后台新增的教师 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, region_id, school_id, school_grade_id, school_class_id, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1029, 'JS1738400001029', '13900000029', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '华老师', '1', '1984-12-12', '2', 420104, 1, 5, 1, '3', '2026-01-18 09:00:00', '0', '000000', 103, 1, NOW(), '0'), +(1030, 'JS1738400001030', '13900000030', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '金老师', '2', '1993-02-14', '2', 420104, 1, 5, 2, '3', '2026-01-19 10:30:00', '0', '000000', 103, 1, NOW(), '0'); + +-- 31: 停用状态的教师 +INSERT INTO pg_member (member_id, member_code, phone, password, nickname, gender, birthday, identity_type, region_id, school_id, school_grade_id, school_class_id, register_source, register_time, status, tenant_id, create_dept, create_by, create_time, del_flag) VALUES +(1031, 'JS1738400001031', '13900000031', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '魏老师(已离职)', '1', '1986-06-06', '2', 420102, 1, 1, 1, '1', '2025-09-01 08:00:00', '1', '000000', 103, 1, NOW(), '0'); + +-- ============================================================ +-- 测试数据统计 +-- ============================================================ +-- 家长会员: 20条 +-- - 正常状态: 18条 +-- - 停用状态: 2条 +-- - 小程序注册: 5条 +-- - H5注册: 5条 +-- - 后台新增: 5条 +-- - 批量导入: 3条 +-- - 有openId: 5条 +-- - 有生日: 14条 +-- - 男性: 9条, 女性: 9条, 未知: 2条 +-- +-- 教师会员: 11条 +-- - 正常状态: 10条 +-- - 停用状态: 1条 +-- - 小程序注册: 5条 +-- - H5注册: 3条 +-- - 后台新增: 2条 +-- - 有openId: 3条 +-- - 男性: 6条, 女性: 5条 +-- ============================================================ + +SELECT '会员测试数据导入完成!' AS message; +SELECT + COUNT(*) AS 总数, + SUM(CASE WHEN identity_type = '1' THEN 1 ELSE 0 END) AS 家长数, + SUM(CASE WHEN identity_type = '2' THEN 1 ELSE 0 END) AS 教师数, + SUM(CASE WHEN status = '0' THEN 1 ELSE 0 END) AS 正常状态, + SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) AS 停用状态 +FROM pg_member WHERE member_id >= 1001 AND member_id <= 1031; diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/member/service/impl/PgMemberServiceImpl.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/member/service/impl/PgMemberServiceImpl.java index ce4a766..1fd2003 100644 --- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/member/service/impl/PgMemberServiceImpl.java +++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/member/service/impl/PgMemberServiceImpl.java @@ -12,7 +12,7 @@ import org.dromara.pangu.member.domain.PgMember; import org.dromara.pangu.member.mapper.PgMemberMapper; import org.dromara.pangu.member.service.IPgMemberService; import org.dromara.pangu.student.mapper.PgStudentMapper; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import cn.hutool.crypto.digest.BCrypt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,7 +32,6 @@ public class PgMemberServiceImpl implements IPgMemberService { private final PgMemberMapper baseMapper; private final PgStudentMapper studentMapper; - private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder(); private static final String DEFAULT_PASSWORD = "123456"; @Override @@ -70,9 +69,9 @@ public class PgMemberServiceImpl implements IPgMemberService { // 密码加密(默认密码) if (StrUtil.isBlank(member.getPassword())) { - member.setPassword(PASSWORD_ENCODER.encode(DEFAULT_PASSWORD)); + member.setPassword(BCrypt.hashpw(DEFAULT_PASSWORD)); } else { - member.setPassword(PASSWORD_ENCODER.encode(member.getPassword())); + member.setPassword(BCrypt.hashpw(member.getPassword())); } // 设置注册时间和来源 @@ -153,7 +152,7 @@ public class PgMemberServiceImpl implements IPgMemberService { PgMember updateMember = new PgMember(); updateMember.setMemberId(memberId); - updateMember.setPassword(PASSWORD_ENCODER.encode(newPassword)); + updateMember.setPassword(BCrypt.hashpw(newPassword)); baseMapper.updateById(updateMember); return newPassword; diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/school/service/impl/PgSchoolServiceImpl.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/school/service/impl/PgSchoolServiceImpl.java index 07b4133..6a7a611 100644 --- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/school/service/impl/PgSchoolServiceImpl.java +++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/school/service/impl/PgSchoolServiceImpl.java @@ -131,16 +131,22 @@ public class PgSchoolServiceImpl implements IPgSchoolService { @Transactional(rollbackFor = Exception.class) public int deleteByIds(Long[] schoolIds) { for (Long schoolId : schoolIds) { - // 1. 检查是否有年级 - Long gradeCount = schoolGradeMapper.selectCount( + // TODO: 检查是否被学生信息引用(学生管理模块完成后添加),有则不允许删除 + + // 级联删除:先删除学校下的所有班级和年级 + List grades = schoolGradeMapper.selectList( new LambdaQueryWrapper().eq(PgSchoolGrade::getSchoolId, schoolId) ); - if (gradeCount > 0) { - PgSchool school = baseMapper.selectById(schoolId); - String schoolName = school != null ? school.getSchoolName() : schoolId.toString(); - throw new RuntimeException("学校\"" + schoolName + "\"下存在年级数据,请先删除年级"); + for (PgSchoolGrade grade : grades) { + // 删除年级下的所有班级 + schoolClassMapper.delete( + new LambdaQueryWrapper().eq(PgSchoolClass::getSchoolGradeId, grade.getId()) + ); } - // TODO: 检查是否被学生信息引用(学生管理模块完成后添加) + // 删除学校下的所有年级 + schoolGradeMapper.delete( + new LambdaQueryWrapper().eq(PgSchoolGrade::getSchoolId, schoolId) + ); } return baseMapper.deleteByIds(Arrays.asList(schoolIds)); } @@ -208,16 +214,13 @@ public class PgSchoolServiceImpl implements IPgSchoolService { @Override @Transactional(rollbackFor = Exception.class) public int removeSchoolGrade(Long schoolGradeId) { - // 1. 检查是否有班级 - Long classCount = schoolClassMapper.selectCount( + // TODO: 检查是否被学生信息引用(学生管理模块完成后添加),有则不允许删除 + + // 级联删除:先删除年级下的所有班级 + schoolClassMapper.delete( new LambdaQueryWrapper().eq(PgSchoolClass::getSchoolGradeId, schoolGradeId) ); - if (classCount > 0) { - throw new RuntimeException("该年级下存在班级数据,请先删除班级"); - } - // TODO: 检查是否被学生信息引用(学生管理模块完成后添加) - - // 2. 删除年级 + // 删除年级 return schoolGradeMapper.deleteById(schoolGradeId); } diff --git a/frontend/ruoyi-ui/src/views/business/school/index.vue b/frontend/ruoyi-ui/src/views/business/school/index.vue index 638df52..8f7d7a2 100644 --- a/frontend/ruoyi-ui/src/views/business/school/index.vue +++ b/frontend/ruoyi-ui/src/views/business/school/index.vue @@ -283,7 +283,7 @@ const countChildren = (node) => { return { gradeCount, classCount } } -// 删除操作 - 删除时提示是否有子级 +// 删除操作 - 删除时提示是否有子级(有子级给出提示,确认后级联删除) const handleDelete = (row, type) => { let message = '' let url = '' @@ -291,25 +291,23 @@ const handleDelete = (row, type) => { if (type === 'school') { const { gradeCount, classCount } = countChildren(row) if (gradeCount > 0 || classCount > 0) { - // 有子级时,提示需要先删除子级 + // 有子级时,提示具体数量,让用户确认后级联删除 let childInfo = [] if (gradeCount > 0) childInfo.push(`${gradeCount}个年级`) if (classCount > 0) childInfo.push(`${classCount}个班级`) - message = `学校"${row.name}"下存在${childInfo.join('、')},请先删除年级和班级后再删除学校。` - ElMessageBox.alert(message, '无法删除', { type: 'warning' }) - return + message = `学校"${row.name}"下存在${childInfo.join('、')},删除后其下的年级和班级也将被删除,确定要删除吗?` + } else { + message = `确定要删除学校"${row.name}"吗?` } - message = `确定要删除学校"${row.name}"吗?` url = `/business/school/${row.id}` } else if (type === 'grade') { const classCount = (row.children || []).filter(c => c.type === 'class').length if (classCount > 0) { - // 有班级时,提示需要先删除班级 - message = `年级"${row.name}"下存在${classCount}个班级,请先删除班级后再删除年级。` - ElMessageBox.alert(message, '无法删除', { type: 'warning' }) - return + // 有班级时,提示具体数量,让用户确认后级联删除 + message = `年级"${row.name}"下存在${classCount}个班级,删除后其下的班级也将被删除,确定要删除吗?` + } else { + message = `确定要删除年级"${row.name}"吗?` } - message = `确定要删除年级"${row.name}"吗?` url = `/business/school/grade/${row.id}` } else { message = `确定要删除班级"${row.name}"吗?`