组织机构管理-单位管理:新增上级单位修改功能,新增单位等级修改功能;允许三级机构,四级机构修改机构信息;

This commit is contained in:
2026-09-30 15:42:24 +08:00
parent 16c47210b7
commit f297210afb
3 changed files with 221 additions and 22 deletions
@@ -33,8 +33,14 @@ public class SysActivityUnitListener implements SysCommonDataChange {
case UPDATE -> {
Sys_unit sys_unit = dao.fetch(Sys_unit.class, bizId);
ActivityBasicUnit basicUnit = dao.fetch(ActivityBasicUnit.class, Cnd.where("id", "=", sys_unit.getId()));
BeanUtil.copyProperties(sys_unit, basicUnit, "id");
dao.update(basicUnit);
if (basicUnit == null) {
// 历史拉取的深层级机构可能未同步到活动单位表,编辑时补齐数据
basicUnit = BeanUtil.copyProperties(sys_unit, ActivityBasicUnit.class);
dao.insert(basicUnit);
} else {
BeanUtil.copyProperties(sys_unit, basicUnit, "id");
dao.update(basicUnit);
}
}
case DELETE -> {
dao.clear(ActivityBasicUnit.class, Cnd.where("id", "=", bizId));
@@ -45,8 +45,10 @@ import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -138,17 +140,39 @@ public class SysUnitController2 {
@RequiresPermissions("sys.manager.unit")
@Aop(TransAop.READ_COMMITTED)
public Object doAdd(Sys_unit sys_unit) {
if (Strings.isBlank(sys_unit.getUnitcode())) {
return Result.error("单位代码不能为空");
}
sys_unit.setId(sys_unit.getUnitcode());
if (Strings.isBlank(sys_unit.getParentId())) {
return Result.error("上级单位不能为空");
}
if (sysUnitService.count(Cnd.where("unitcode", "=", sys_unit.getUnitcode())) > 0) {
return Result.error("单位代码已存在");
}
Sys_unit parentUnit = sysUnitService.fetch(sys_unit.getParentId());
if (parentUnit == null) {
return Result.error("上级单位不存在");
}
int calculatedUnitLevel = calculateUnitLevel(parentUnit, sys_unit.getId());
if (calculatedUnitLevel < 0) {
return Result.error("单位层级关系异常");
}
Integer unitLevel = sys_unit.getUnitlevel();
if (unitLevel == null) {
unitLevel = calculatedUnitLevel;
} else if (unitLevel < 1) {
return Result.error("单位等级不能小于1");
}
sys_unit.setUnitlevel(unitLevel);
sys_unit.setPath(sysUnitService.getSubPath("sys_unit", "path", parentUnit.getPath()));
sysUnitService.update(Chain.make("hasChildren", true), Cnd.where("id", "=", sys_unit.getParentId()));
sysUnitService.insert(sys_unit);
// 通知系统单位发生变更
SysCommonDataChangeCenter.publish(SysCommonDataChangeType.INSERT, Sys_unit.class, sys_unit.getId());
return null;
return Result.success().addData(sysUnitService.fetch(sys_unit.getId()));
}
@@ -157,15 +181,80 @@ public class SysUnitController2 {
@RequiresPermissions("sys.manager.unit")
@Aop(TransAop.READ_COMMITTED)
public Object doEdit(Sys_unit sys_unit) {
if (Strings.isBlank(sys_unit.getId()) || Strings.isBlank(sys_unit.getParentId())) {
return Result.error("单位或上级单位不能为空");
}
if (sysUnitService.count(Cnd.where("unitcode", "=", sys_unit.getUnitcode()).and("id", "!=", sys_unit.getId())) > 0) {
return Result.error("单位代码已存在");
}
Sys_unit oldUnit = sysUnitService.fetch(sys_unit.getId());
Sys_unit parentUnit = sysUnitService.fetch(sys_unit.getParentId());
if (oldUnit == null || parentUnit == null) {
return Result.error("单位信息不存在");
}
if (sys_unit.getId().equals(sys_unit.getParentId())) {
return Result.error("上级单位不能选择自身");
}
String oldParentId = oldUnit.getParentId();
boolean parentChanged = !Strings.sBlank(oldParentId).equals(Strings.sBlank(sys_unit.getParentId()));
int calculatedUnitLevel = calculateUnitLevel(parentUnit, sys_unit.getId());
if (calculatedUnitLevel < 0) {
return Result.error("上级单位不能选择当前单位或其下级单位");
}
Integer unitLevel = sys_unit.getUnitlevel();
if (unitLevel == null) {
unitLevel = calculatedUnitLevel;
} else if (unitLevel < 1) {
return Result.error("单位等级不能小于1");
}
sys_unit.setUnitlevel(unitLevel);
sys_unit.setHasChildren(oldUnit.isHasChildren());
if (parentChanged) {
sys_unit.setPath(sysUnitService.getSubPath("sys_unit", "path", parentUnit.getPath()));
} else {
sys_unit.setPath(oldUnit.getPath());
}
sys_unit.setOpAt(System.currentTimeMillis());
sysUnitService.update(sys_unit);
// 单位等级允许手工指定,未填写时使用根据父级链计算出的等级
sysUnitService.update(Chain.make("parentId", sys_unit.getParentId())
.add("unitlevel", unitLevel)
.add("path", sys_unit.getPath()),
Cnd.where("id", "=", sys_unit.getId()));
if (parentChanged) {
int oldParentChildren = sysUnitService.count(Cnd.where("parentId", "=", oldParentId));
sysUnitService.update(Chain.make("hasChildren", oldParentChildren > 0), Cnd.where("id", "=", oldParentId));
sysUnitService.update(Chain.make("hasChildren", true), Cnd.where("id", "=", sys_unit.getParentId()));
}
// 通知系统单位发生变更
SysCommonDataChangeCenter.publish(SysCommonDataChangeType.UPDATE, Sys_unit.class, sys_unit.getId());
return null;
return Result.success().addData(sysUnitService.fetch(sys_unit.getId()));
}
/**
* 根据实际父级链计算单位等级,根单位为0级,根单位的下级为1级。
*/
private int calculateUnitLevel(Sys_unit parentUnit, String unitId) {
int unitLevel = 0;
Set<String> parentIds = new HashSet<>();
Sys_unit currentUnit = parentUnit;
while (currentUnit != null) {
if ((Strings.isNotBlank(unitId) && unitId.equals(currentUnit.getId())) ||
!parentIds.add(currentUnit.getId())) {
return -1;
}
unitLevel++;
if (Strings.isBlank(currentUnit.getParentId()) || currentUnit.getId().equals(currentUnit.getParentId())) {
break;
}
currentUnit = sysUnitService.fetch(currentUnit.getParentId());
}
return unitLevel;
}
@At
@@ -278,7 +278,7 @@ layout("/layouts/platform.html"){
<el-card shadow="never" class="mt10">
<el-tabs v-model="secondaryTabActiveName" type="card"
@tab-click="secondaryDataSearch()">
<el-tab-pane label="三级单位" name="thirdLevelUnit"></el-tab-pane>
<el-tab-pane label="二级单位" name="thirdLevelUnit"></el-tab-pane>
<el-tab-pane label="单位人员" name="unitPersonnel"></el-tab-pane>
<el-tab-pane label="单位负责人" name="unitLeader"></el-tab-pane>
<el-tab-pane label="单位分管校领导" name="unitSchoolLeader"></el-tab-pane>
@@ -413,7 +413,7 @@ layout("/layouts/platform.html"){
</el-card>
</div>
<div v-if="checkNode.level===3" style="padding: 0 10px">
<div v-if="checkNode.level>=3" style="padding: 0 10px">
<el-card shadow="never">
<div class="btn-group tool-button mt5">
<el-input placeholder="请输入内容" clearable
@@ -432,6 +432,13 @@ layout("/layouts/platform.html"){
<div class="btn-group tool-button mt5">
<el-button type="primary" icon="el-icon-search" @click="thirdPageData"></el-button>
</div>
<div class="pull-right offscreen-right mt5">
<div class="btn-group tool-button">
<el-button icon="el-icon-edit" type="primary" @click="openEdit(checkData.id)">
编辑单位
</el-button>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt10">
@@ -500,19 +507,30 @@ layout("/layouts/platform.html"){
label-width="120px"
style="padding: 0 30px">
<el-row gutter="30">
<el-col :span="24">
<el-form-item label="上级单位">
<el-input maxlength="100" disabled :value="checkData.name"
type="text"></el-input>
<el-col :span="12">
<el-form-item label="上级单位" prop="parentId">
<el-cascader v-model="formData.parentId"
:options="parentUnitOptions"
:props="parentUnitProps"
:show-all-levels="false"
placeholder="请选择上级单位"
style="width: 100%"></el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位名称" prop="name">
<el-input maxlength="100" placeholder="请输入单位名称" v-model="formData.name"
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row gutter="30">
<el-col :span="12">
<el-form-item label="单位等级" prop="unitlevel">
<el-input v-model="formData.unitlevel" clearable @input="unitLevelInput"
placeholder="不填写则按上级单位自动计算"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位代码" prop="unitcode">
<el-input maxlength="100" placeholder="请输入单位编码" v-model="formData.unitcode"
@@ -520,7 +538,8 @@ layout("/layouts/platform.html"){
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row gutter="30">
<el-col :span="12">
<el-form-item label="单位简称" prop="aliasName">
<el-input maxlength="100" placeholder="请输入单位简称" v-model="formData.aliasName"
@@ -533,7 +552,8 @@ layout("/layouts/platform.html"){
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row gutter="30">
<el-col :span="12">
<el-form-item label="单位邮箱" prop="email">
<el-input maxlength="100" placeholder="请输入单位邮箱" v-model="formData.email"
@@ -546,13 +566,16 @@ layout("/layouts/platform.html"){
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row gutter="30">
<el-col :span="24">
<el-form-item label="单位地址" prop="address">
<el-input maxlength="100" placeholder="请输入单位地址" v-model="formData.address"
type="text"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row gutter="30">
<el-col :span="24">
<el-form-item label="单位介绍" prop="note">
<el-input maxlength="500" type="textarea" placeholder="请输入单位介绍"
@@ -665,7 +688,15 @@ layout("/layouts/platform.html"){
},
formRules: {
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
code: [{required: true, message: '必填', trigger: ['blur', 'change']}],
unitcode: [{required: true, message: '必填', trigger: ['blur', 'change']}],
parentId: [{required: true, message: '必填', trigger: 'change'}],
},
parentUnitProps: {
value: 'id',
label: 'name',
children: 'child',
checkStrictly: true,
emitPath: false,
},
checkNode: {level: 1},
checkData: {},
@@ -710,6 +741,29 @@ layout("/layouts/platform.html"){
}
},
computed: {
parentUnitOptions() {
const disabledIds = new Set()
const collectDisabledIds = (units, parentDisabled) => units.forEach(unit => {
const disabled = parentDisabled || unit.id === this.formData.id
if (disabled) {
disabledIds.add(unit.id)
}
if (unit.child && unit.child.length) {
collectDisabledIds(unit.child, disabled)
}
})
collectDisabledIds(this.treeData, false)
const buildOptions = units => units.map(unit => ({
...unit,
// 当前单位及其所有下级不能作为上级单位,避免形成循环层级
disabled: disabledIds.has(unit.id),
child: unit.child && unit.child.length ? buildOptions(unit.child) : undefined,
}))
return buildOptions(this.treeData)
}
},
mounted() {
setTimeout(() => {
if (this.$refs.firstTable) {
@@ -727,6 +781,37 @@ layout("/layouts/platform.html"){
}
},
methods: {
async confirmUnitLevel() {
const inputLevel = this.formData.unitlevel
if (inputLevel === '' || inputLevel === null || inputLevel === undefined) {
return true
}
const parentNode = this.$refs.tree.getNode(this.formData.parentId)
if (!parentNode || Number(inputLevel) === parentNode.level) {
return true
}
try {
await this.$confirm(
'根据当前上级单位,推荐单位等级为' + parentNode.level +
'级,当前填写为' + inputLevel + '级,是否仍按当前等级保存?',
'单位等级确认',
{
confirmButtonText: '继续保存',
cancelButtonText: '返回修改',
type: 'warning'
}
)
return true
} catch (e) {
return false
}
},
unitLevelInput(value) {
const unitLevel = String(value || '').replace(/\D/g, '')
if (unitLevel !== value) {
this.$set(this.formData, 'unitlevel', unitLevel)
}
},
async openAddOtherRole() {
this.otherRoleDialogVisible = true
if (this.$refs.otherRoleTransfer) {
@@ -856,7 +941,7 @@ layout("/layouts/platform.html"){
this.doSearch()
} else if (node.level === 2) {
this.secondaryDataSearch()
} else if (node.level === 3) {
} else if (node.level >= 3) {
this.thirdPageData()
}
},
@@ -891,14 +976,31 @@ layout("/layouts/platform.html"){
doEdit() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
if (!await this.confirmUnitLevel()) {
return
}
this.loading = true
const resp = await $.post(loc() + "/doEdit", this.formData)
this.loading = false
if (resp.code === 0) {
this.loadTree(false)
this.pageData();
this.secondaryDataSearch()
this.thirdPageData()
const editedUnit = resp.data || this.formData
if (this.checkData.id === this.formData.id) {
this.checkData = Object.assign({}, this.checkData, editedUnit)
}
await this.loadTree(false)
await this.$nextTick()
const currentNode = this.$refs.tree.getNode(this.checkData.id)
if (currentNode) {
this.checkNode = currentNode
this.checkData = currentNode.data
}
if (this.checkNode.level === 1) {
this.pageData()
} else if (this.checkNode.level === 2) {
this.secondaryDataSearch()
} else {
this.thirdPageData()
}
this.$refs.guava.index()
} else {
this.$notify.warning(resp.msg)
@@ -922,6 +1024,9 @@ layout("/layouts/platform.html"){
doAdd() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
if (!await this.confirmUnitLevel()) {
return
}
this.loading = true
const resp = await $.post(loc() + "/doAdd", this.formData)
this.loading = false
@@ -938,10 +1043,9 @@ layout("/layouts/platform.html"){
});
},
openAdd() {
const {id, unitlevel} = this.checkData
const {id} = this.checkData
this.formData = {
parentId: id,
unitlevel: unitlevel + 1,
}
this.$refs.guava.edit()
if (this.$refs['form']) {