diff --git a/src/main/java/io/v/nutz/activity/listener/SysActivityUnitListener.java b/src/main/java/io/v/nutz/activity/listener/SysActivityUnitListener.java index e565626..4bf6074 100644 --- a/src/main/java/io/v/nutz/activity/listener/SysActivityUnitListener.java +++ b/src/main/java/io/v/nutz/activity/listener/SysActivityUnitListener.java @@ -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)); diff --git a/src/main/java/io/v/nutz/web/modules/controllers/platform/sys/SysUnitController2.java b/src/main/java/io/v/nutz/web/modules/controllers/platform/sys/SysUnitController2.java index 0ac8783..1f6bf7f 100644 --- a/src/main/java/io/v/nutz/web/modules/controllers/platform/sys/SysUnitController2.java +++ b/src/main/java/io/v/nutz/web/modules/controllers/platform/sys/SysUnitController2.java @@ -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 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 diff --git a/src/main/resources/views/platform/sys/unit/unitMange.html b/src/main/resources/views/platform/sys/unit/unitMange.html index 60d7018..6d974f5 100644 --- a/src/main/resources/views/platform/sys/unit/unitMange.html +++ b/src/main/resources/views/platform/sys/unit/unitMange.html @@ -278,7 +278,7 @@ layout("/layouts/platform.html"){ - + @@ -413,7 +413,7 @@ layout("/layouts/platform.html"){ -
+
+
+
+ + 编辑单位 + +
+
@@ -500,19 +507,30 @@ layout("/layouts/platform.html"){ label-width="120px" style="padding: 0 30px"> - - - + + + - + + + + + + + - + + - + + - + + + + 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']) {