feat: 新增学校自动添加年级 + 修复区域层级查询 + 清理区域数据
1. 新增学校时根据学段自动添加对应年级 2. 修复选择省/市时无法显示学校的bug(支持区域层级查询) 3. 区域树默认展开湖北省,平行显示市级 4. 新增区域数据清理SQL脚本(仅保留湖北省)
This commit is contained in:
parent
72cb6668f3
commit
add00c9992
|
|
@ -1,6 +1,7 @@
|
|||
package org.dromara.pangu.base.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
|
|
@ -13,6 +14,7 @@ import org.dromara.pangu.base.service.IPgGradeService;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -39,9 +41,16 @@ public class PgGradeController extends BaseController {
|
|||
|
||||
/**
|
||||
* 查询年级列表(不分页)
|
||||
* @param grade 查询条件
|
||||
* @param stages 学段列表,逗号分隔(如:1,2 表示小学和初中)
|
||||
*/
|
||||
@GetMapping("/listAll")
|
||||
public R<List<PgGrade>> listAll(PgGrade grade) {
|
||||
public R<List<PgGrade>> listAll(PgGrade grade,
|
||||
@RequestParam(required = false) String stages) {
|
||||
if (StrUtil.isNotBlank(stages)) {
|
||||
List<String> stageList = Arrays.asList(stages.split(","));
|
||||
return R.ok(gradeService.selectListByStages(stageList));
|
||||
}
|
||||
return R.ok(gradeService.selectList(grade));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,4 +42,10 @@ public interface IPgGradeService {
|
|||
* 批量删除年级
|
||||
*/
|
||||
int deleteByIds(Long[] gradeIds);
|
||||
|
||||
/**
|
||||
* 根据学段列表查询年级
|
||||
* @param stages 学段列表(1小学 2初中 3高中 4中专 5大学)
|
||||
*/
|
||||
List<PgGrade> selectListByStages(List<String> stages);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,19 @@ public class PgGradeServiceImpl implements IPgGradeService {
|
|||
return baseMapper.deleteByIds(Arrays.asList(gradeIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PgGrade> selectListByStages(List<String> stages) {
|
||||
if (stages == null || stages.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return baseMapper.selectList(
|
||||
new LambdaQueryWrapper<PgGrade>()
|
||||
.in(PgGrade::getStage, stages)
|
||||
.eq(PgGrade::getStatus, "0")
|
||||
.orderByAsc(PgGrade::getOrderNum)
|
||||
);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<PgGrade> buildQueryWrapper(PgGrade grade) {
|
||||
LambdaQueryWrapper<PgGrade> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.like(StrUtil.isNotBlank(grade.getGradeName()), PgGrade::getGradeName, grade.getGradeName());
|
||||
|
|
|
|||
|
|
@ -60,4 +60,10 @@ public class PgSchool extends BaseEntity {
|
|||
*/
|
||||
@TableField(exist = false)
|
||||
private String regionName;
|
||||
|
||||
/**
|
||||
* 初始年级ID列表(非数据库字段,用于新增时批量添加年级)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private java.util.List<Long> gradeIds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,14 @@ public class PgSchoolServiceImpl implements IPgSchoolService {
|
|||
school.setDeptId(deptBo.getDeptId());
|
||||
}
|
||||
|
||||
return baseMapper.insert(school);
|
||||
int result = baseMapper.insert(school);
|
||||
|
||||
// 如果传入了初始年级ID列表,批量添加到学校
|
||||
if (school.getGradeIds() != null && !school.getGradeIds().isEmpty()) {
|
||||
addSchoolGrades(school.getSchoolId(), school.getGradeIds());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,11 +302,39 @@ public class PgSchoolServiceImpl implements IPgSchoolService {
|
|||
LambdaQueryWrapper<PgSchool> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.like(StrUtil.isNotBlank(school.getSchoolName()), PgSchool::getSchoolName, school.getSchoolName());
|
||||
lqw.eq(StrUtil.isNotBlank(school.getSchoolType()), PgSchool::getSchoolType, school.getSchoolType());
|
||||
lqw.eq(school.getRegionId() != null, PgSchool::getRegionId, school.getRegionId());
|
||||
|
||||
// 区域查询:支持查询选定区域及其所有下级区域的学校
|
||||
if (school.getRegionId() != null) {
|
||||
List<Long> regionIds = getRegionIdsWithChildren(school.getRegionId());
|
||||
if (!regionIds.isEmpty()) {
|
||||
lqw.in(PgSchool::getRegionId, regionIds);
|
||||
}
|
||||
}
|
||||
|
||||
lqw.eq(StrUtil.isNotBlank(school.getStatus()), PgSchool::getStatus, school.getStatus());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定区域及其所有下级区域的ID列表
|
||||
* @param regionId 区域ID
|
||||
* @return 包含该区域及所有下级区域的ID列表
|
||||
*/
|
||||
private List<Long> getRegionIdsWithChildren(Long regionId) {
|
||||
List<Long> result = new ArrayList<>();
|
||||
result.add(regionId);
|
||||
|
||||
// 递归查询下级区域
|
||||
List<PgRegion> children = regionMapper.selectList(
|
||||
new LambdaQueryWrapper<PgRegion>().eq(PgRegion::getParentId, regionId)
|
||||
);
|
||||
for (PgRegion child : children) {
|
||||
result.addAll(getRegionIdsWithChildren(child.getRegionId()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SchoolTreeNode> selectSchoolTree(PgSchool school) {
|
||||
// 查询学校列表(使用带数据权限的查询方法)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,26 @@
|
|||
inactive-text="停用"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 新增时显示年级选择区域 -->
|
||||
<el-form-item v-if="!isEdit && gradeList.length > 0" label="初始年级">
|
||||
<div class="grade-select-wrapper">
|
||||
<el-checkbox-group v-model="selectedGradeIds">
|
||||
<el-checkbox
|
||||
v-for="grade in gradeList"
|
||||
:key="grade.gradeId"
|
||||
:value="grade.gradeId"
|
||||
:label="grade.gradeId"
|
||||
>
|
||||
{{ grade.gradeName }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<div class="grade-tip">
|
||||
<el-text type="info" size="small">
|
||||
已选择 {{ selectedGradeIds.length }} 个年级,将在学校创建后自动添加
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
|
|
@ -77,9 +97,10 @@
|
|||
* @author pangu
|
||||
*/
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { addSchool, updateSchool } from '@/api/pangu/school'
|
||||
import { deptTreeSelect } from '@/api/system/user'
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 接收父组件传递的区域树
|
||||
const props = defineProps({
|
||||
|
|
@ -99,6 +120,10 @@ const submitLoading = ref(false)
|
|||
const formRef = ref(null)
|
||||
const isEdit = ref(false)
|
||||
|
||||
// 年级列表和选中的年级ID
|
||||
const gradeList = ref([])
|
||||
const selectedGradeIds = ref([])
|
||||
|
||||
// 表单数据
|
||||
const form = ref({
|
||||
schoolId: null,
|
||||
|
|
@ -159,6 +184,51 @@ const handleRegionChange = (value) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 学校类型对应学段映射
|
||||
const getStagesBySchoolType = (schoolType) => {
|
||||
const map = {
|
||||
'1': ['1'], // 小学
|
||||
'2': ['2'], // 初中
|
||||
'3': ['3'], // 高中
|
||||
'4': ['1', '2'], // 九年一贯制
|
||||
'5': ['2', '3'] // 完全中学
|
||||
}
|
||||
return map[schoolType] || []
|
||||
}
|
||||
|
||||
// 根据学校类型加载年级列表
|
||||
const loadGradesBySchoolType = async (schoolType) => {
|
||||
const stages = getStagesBySchoolType(schoolType)
|
||||
if (stages.length === 0) {
|
||||
gradeList.value = []
|
||||
selectedGradeIds.value = []
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await request.get('/business/grade/listAll', {
|
||||
params: { stages: stages.join(',') }
|
||||
})
|
||||
if (res.code === 200) {
|
||||
gradeList.value = res.data || []
|
||||
// 默认全选
|
||||
selectedGradeIds.value = gradeList.value.map(g => g.gradeId)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载年级列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听学校类型变化,自动加载对应年级(仅新增模式)
|
||||
watch(() => form.value.schoolType, async (newType) => {
|
||||
if (!isEdit.value && newType) {
|
||||
await loadGradesBySchoolType(newType)
|
||||
} else if (!newType) {
|
||||
gradeList.value = []
|
||||
selectedGradeIds.value = []
|
||||
}
|
||||
})
|
||||
|
||||
// 加载部门树
|
||||
const loadDeptTree = async () => {
|
||||
try {
|
||||
|
|
@ -208,6 +278,9 @@ const open = async (row, defaultRegionId = null) => {
|
|||
regionName: defaultRegionId ? getRegionPath(regionIds, props.regionTree) : '',
|
||||
status: '0'
|
||||
}
|
||||
// 重置年级选择
|
||||
gradeList.value = []
|
||||
selectedGradeIds.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +319,8 @@ const handleSubmit = async () => {
|
|||
try {
|
||||
const submitData = {
|
||||
...form.value,
|
||||
regionIds: undefined // 不提交级联选择器的数组
|
||||
regionIds: undefined, // 不提交级联选择器的数组
|
||||
gradeIds: isEdit.value ? undefined : selectedGradeIds.value // 新增时携带年级ID列表
|
||||
}
|
||||
|
||||
const res = form.value.schoolId
|
||||
|
|
@ -254,7 +328,11 @@ const handleSubmit = async () => {
|
|||
: await addSchool(submitData)
|
||||
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(isEdit.value ? '修改成功' : '新增成功')
|
||||
const gradeCount = selectedGradeIds.value.length
|
||||
const msg = isEdit.value
|
||||
? '修改成功'
|
||||
: (gradeCount > 0 ? `新增成功,已自动添加 ${gradeCount} 个年级` : '新增成功')
|
||||
ElMessage.success(msg)
|
||||
dialogVisible.value = false
|
||||
emit('success')
|
||||
}
|
||||
|
|
@ -269,3 +347,16 @@ const handleSubmit = async () => {
|
|||
// 暴露方法给父组件
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.grade-select-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.grade-select-wrapper .el-checkbox {
|
||||
margin-right: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.grade-tip {
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
:props="{ label: 'regionName', children: 'children' }"
|
||||
node-key="regionId"
|
||||
highlight-current
|
||||
:default-expanded-keys="defaultExpandedKeys"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
|
|
@ -140,6 +141,8 @@ const treeRef = ref()
|
|||
const treeFilterText = ref('')
|
||||
const regionTree = ref([])
|
||||
const selectedRegionId = ref(null)
|
||||
// 默认展开湖北省(regionId=42),只展开一级显示市级
|
||||
const defaultExpandedKeys = ref([42])
|
||||
|
||||
// 表格相关
|
||||
const loading = ref(false)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
-- ================================================================
|
||||
-- V1.0.5 清理非湖北省区域数据
|
||||
-- 执行说明:先检查湖北省的region_id,确认为42后再执行删除
|
||||
-- 执行时间:需在业务低峰期执行
|
||||
-- ================================================================
|
||||
|
||||
-- 0. 首先确认湖北省的region_id
|
||||
SELECT region_id, region_name, parent_id, ancestors FROM pg_region WHERE region_name = '湖北省';
|
||||
-- 预期结果:region_id = 42
|
||||
|
||||
-- 1. 查看要删除的数据量(预检查,不会执行删除)
|
||||
SELECT COUNT(*) as '待删除的区域数量' FROM pg_region
|
||||
WHERE region_id != 42
|
||||
AND ancestors NOT LIKE '0,42%';
|
||||
|
||||
-- 2. 物理删除非湖北省的区域数据
|
||||
-- 删除所有ancestors不以"0,42"开头的区域(即非湖北省及其下级区域)
|
||||
-- 同时排除湖北省本身(region_id=42)
|
||||
DELETE FROM pg_region
|
||||
WHERE region_id != 42
|
||||
AND ancestors NOT LIKE '0,42%';
|
||||
|
||||
-- 3. 删除其他省份的根节点(parent_id = 0 且 region_id != 42)
|
||||
DELETE FROM pg_region
|
||||
WHERE parent_id = 0
|
||||
AND region_id != 42;
|
||||
|
||||
-- 4. 验证结果
|
||||
SELECT COUNT(*) as '剩余区域数量' FROM pg_region;
|
||||
SELECT region_name, level, COUNT(*) as '数量' FROM pg_region GROUP BY level, region_name LIMIT 20;
|
||||
Loading…
Reference in New Issue