From 815369ca82e3f61b70c3b2a3035b8fe68046ee02 Mon Sep 17 00:00:00 2001 From: qiankanghui Date: Thu, 23 Apr 2026 15:19:46 +0800 Subject: [PATCH] =?UTF-8?q?feat(factory):=20=E6=B7=BB=E5=8A=A0=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E6=88=90=E5=91=98=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 AccessDeptListMembersRequest DTO 类用于查询部门成员列表 - 创建 AccessDeptMemberController 控制器实现部门成员的增删改查接口 - 添加 AccessDeptMemberDeleteRequest 和 AccessDeptMemberSaveRequest DTO 类 - 实现 AccessDeptMemberService 接口定义部门成员管理业务方法 - 提供 AccessDeptMemberServiceImpl 服务实现类包含完整的业务逻辑 - 扩展 SiteMapper 数据访问接口添加部门成员相关操作方法 - 在 SiteMapper.xml 中实现新增的部门成员管理 SQL 映射语句 - 添加部门成员验证逻辑包括上级关系检查和循环引用防护 - 实现部门成员的保存、更新、删除和查询功能 --- .../AccessDeptMemberController.java | 54 ++++++ .../xujie/modules/factory/dao/SiteMapper.java | 17 ++ .../dto/AccessDeptListMembersRequest.java | 39 ++++ .../dto/AccessDeptMemberDeleteRequest.java | 48 +++++ .../dto/AccessDeptMemberSaveRequest.java | 75 ++++++++ .../dto/UserAccessDeptQueryRequest.java | 21 +++ .../service/AccessDeptMemberService.java | 22 +++ .../impl/AccessDeptMemberServiceImpl.java | 170 ++++++++++++++++++ .../sys/entity/SysDepartmentEntity.java | 37 ++++ .../resources/mapper/factory/SiteMapper.xml | 75 +++++++- .../mapper/sys/SysDepartmentMapper.xml | 2 + 11 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/xujie/modules/factory/controller/AccessDeptMemberController.java create mode 100644 src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptListMembersRequest.java create mode 100644 src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberDeleteRequest.java create mode 100644 src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberSaveRequest.java create mode 100644 src/main/java/com/xujie/modules/factory/entity/dto/UserAccessDeptQueryRequest.java create mode 100644 src/main/java/com/xujie/modules/factory/service/AccessDeptMemberService.java create mode 100644 src/main/java/com/xujie/modules/factory/service/impl/AccessDeptMemberServiceImpl.java diff --git a/src/main/java/com/xujie/modules/factory/controller/AccessDeptMemberController.java b/src/main/java/com/xujie/modules/factory/controller/AccessDeptMemberController.java new file mode 100644 index 0000000..f971b48 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/controller/AccessDeptMemberController.java @@ -0,0 +1,54 @@ +package com.xujie.modules.factory.controller; + +import com.xujie.common.utils.R; +import com.xujie.modules.factory.entity.dto.AccessDeptListMembersRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberDeleteRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberSaveRequest; +import com.xujie.modules.factory.entity.dto.UserAccessDeptQueryRequest; +import com.xujie.modules.factory.service.AccessDeptMemberService; +import com.xujie.modules.sys.entity.SysDepartmentEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RequestMapping("/site/accessDept") +@RestController +public class AccessDeptMemberController { + + @Autowired + private AccessDeptMemberService accessDeptMemberService; + + @PostMapping("/listMembers") + public R listMembers(@RequestBody AccessDeptListMembersRequest request) { + List list = accessDeptMemberService.listMembers(request); + return R.ok().put("list", list); + } + + @PostMapping("/saveMember") + public R saveMember(@RequestBody AccessDeptMemberSaveRequest request) { + accessDeptMemberService.saveMember(request); + return R.ok(); + } + + @PostMapping("/updateMember") + public R updateMember(@RequestBody AccessDeptMemberSaveRequest request) { + accessDeptMemberService.updateMember(request); + return R.ok(); + } + + @PostMapping("/deleteMember") + public R deleteMember(@RequestBody AccessDeptMemberDeleteRequest request) { + accessDeptMemberService.deleteMember(request); + return R.ok(); + } + + @PostMapping("/listByUsername") + public R listByUsername(@RequestBody UserAccessDeptQueryRequest request) { + List list = accessDeptMemberService.listByUsername(request); + return R.ok().put("list", list); + } +} diff --git a/src/main/java/com/xujie/modules/factory/dao/SiteMapper.java b/src/main/java/com/xujie/modules/factory/dao/SiteMapper.java index caf192d..53399f6 100644 --- a/src/main/java/com/xujie/modules/factory/dao/SiteMapper.java +++ b/src/main/java/com/xujie/modules/factory/dao/SiteMapper.java @@ -85,4 +85,21 @@ public interface SiteMapper extends BaseMapper { List getEmpyDeptList(EmpyDept data); List getSite2(SiteVo data); + + List listAccessDeptMembers(SysDepartmentEntity deptKey); + + void insertAccessDeptMember(SysDepartmentEntity row); + + void updateAccessDeptMember(SysDepartmentEntity row); + + int countDirectReportsInDept(SysDepartmentEntity row); + + void deleteAccessDeptMember(SysDepartmentEntity row); + + List listAccessDeptByUsername(SysDepartmentEntity query); + + int countMemberInDept(SysDepartmentEntity row); + + String selectSuperiorUsernameInDept(SysDepartmentEntity row); + } diff --git a/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptListMembersRequest.java b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptListMembersRequest.java new file mode 100644 index 0000000..8fe8711 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptListMembersRequest.java @@ -0,0 +1,39 @@ +package com.xujie.modules.factory.entity.dto; + +import java.io.Serializable; + +/** + * 查询某部门下的成员列表 + */ +public class AccessDeptListMembersRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String site; + private String buNo; + private String departmentId; + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getBuNo() { + return buNo; + } + + public void setBuNo(String buNo) { + this.buNo = buNo; + } + + public String getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(String departmentId) { + this.departmentId = departmentId; + } +} diff --git a/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberDeleteRequest.java b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberDeleteRequest.java new file mode 100644 index 0000000..5ae50fc --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberDeleteRequest.java @@ -0,0 +1,48 @@ +package com.xujie.modules.factory.entity.dto; + +import java.io.Serializable; + +/** + * 从部门移除成员 + */ +public class AccessDeptMemberDeleteRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String site; + private String buNo; + private String departmentId; + private String username; + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getBuNo() { + return buNo; + } + + public void setBuNo(String buNo) { + this.buNo = buNo; + } + + public String getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(String departmentId) { + this.departmentId = departmentId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberSaveRequest.java b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberSaveRequest.java new file mode 100644 index 0000000..3672e89 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/entity/dto/AccessDeptMemberSaveRequest.java @@ -0,0 +1,75 @@ +package com.xujie.modules.factory.entity.dto; + +import java.io.Serializable; + +/** + * 新增或更新部门成员 + */ +public class AccessDeptMemberSaveRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String site; + private String buNo; + private String departmentId; + private String username; + private String jobTitle; + private String deptManagerFlag; + private String superiorUsername; + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getBuNo() { + return buNo; + } + + public void setBuNo(String buNo) { + this.buNo = buNo; + } + + public String getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(String departmentId) { + this.departmentId = departmentId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getJobTitle() { + return jobTitle; + } + + public void setJobTitle(String jobTitle) { + this.jobTitle = jobTitle; + } + + public String getDeptManagerFlag() { + return deptManagerFlag; + } + + public void setDeptManagerFlag(String deptManagerFlag) { + this.deptManagerFlag = deptManagerFlag; + } + + public String getSuperiorUsername() { + return superiorUsername; + } + + public void setSuperiorUsername(String superiorUsername) { + this.superiorUsername = superiorUsername; + } +} diff --git a/src/main/java/com/xujie/modules/factory/entity/dto/UserAccessDeptQueryRequest.java b/src/main/java/com/xujie/modules/factory/entity/dto/UserAccessDeptQueryRequest.java new file mode 100644 index 0000000..35c79b9 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/entity/dto/UserAccessDeptQueryRequest.java @@ -0,0 +1,21 @@ +package com.xujie.modules.factory.entity.dto; + +import java.io.Serializable; + +/** + * 按用户查询其全部 Access_dept 记录 + */ +public class UserAccessDeptQueryRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String username; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/src/main/java/com/xujie/modules/factory/service/AccessDeptMemberService.java b/src/main/java/com/xujie/modules/factory/service/AccessDeptMemberService.java new file mode 100644 index 0000000..1a13cc4 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/service/AccessDeptMemberService.java @@ -0,0 +1,22 @@ +package com.xujie.modules.factory.service; + +import com.xujie.modules.factory.entity.dto.AccessDeptListMembersRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberDeleteRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberSaveRequest; +import com.xujie.modules.factory.entity.dto.UserAccessDeptQueryRequest; +import com.xujie.modules.sys.entity.SysDepartmentEntity; + +import java.util.List; + +public interface AccessDeptMemberService { + + List listMembers(AccessDeptListMembersRequest request); + + void saveMember(AccessDeptMemberSaveRequest request); + + void updateMember(AccessDeptMemberSaveRequest request); + + void deleteMember(AccessDeptMemberDeleteRequest request); + + List listByUsername(UserAccessDeptQueryRequest request); +} diff --git a/src/main/java/com/xujie/modules/factory/service/impl/AccessDeptMemberServiceImpl.java b/src/main/java/com/xujie/modules/factory/service/impl/AccessDeptMemberServiceImpl.java new file mode 100644 index 0000000..2a8edb4 --- /dev/null +++ b/src/main/java/com/xujie/modules/factory/service/impl/AccessDeptMemberServiceImpl.java @@ -0,0 +1,170 @@ +package com.xujie.modules.factory.service.impl; + +import com.xujie.modules.factory.dao.SiteMapper; +import com.xujie.modules.factory.entity.dto.AccessDeptListMembersRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberDeleteRequest; +import com.xujie.modules.factory.entity.dto.AccessDeptMemberSaveRequest; +import com.xujie.modules.factory.entity.dto.UserAccessDeptQueryRequest; +import com.xujie.modules.factory.service.AccessDeptMemberService; +import com.xujie.modules.sys.entity.SysDepartmentEntity; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class AccessDeptMemberServiceImpl implements AccessDeptMemberService { + + @Autowired + private SiteMapper siteMapper; + + @Override + public List listMembers(AccessDeptListMembersRequest request) { + requireDeptKey(request.getSite(), request.getBuNo(), request.getDepartmentId()); + SysDepartmentEntity key = new SysDepartmentEntity(); + key.setSite(trimToNull(request.getSite())); + key.setBuNo(trimToNull(request.getBuNo())); + key.setDepartmentId(trimToNull(request.getDepartmentId())); + List list = siteMapper.listAccessDeptMembers(key); + return list != null ? list : new ArrayList<>(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveMember(AccessDeptMemberSaveRequest request) { + requireDeptKey(request.getSite(), request.getBuNo(), request.getDepartmentId()); + String username = trimToNull(request.getUsername()); + if (username == null) { + throw new RuntimeException("账号不能为空"); + } + SysDepartmentEntity row = toEntity(request); + SysDepartmentEntity exists = siteMapper.selectDeptByUserName(row); + if (exists != null) { + throw new RuntimeException("该用户已在本部门中"); + } + validateSuperiorChain(row.getSite(), row.getBuNo(), row.getDepartmentId(), username, row.getSuperiorUsername()); + siteMapper.insertAccessDeptMember(row); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMember(AccessDeptMemberSaveRequest request) { + requireDeptKey(request.getSite(), request.getBuNo(), request.getDepartmentId()); + String username = trimToNull(request.getUsername()); + if (username == null) { + throw new RuntimeException("账号不能为空"); + } + SysDepartmentEntity row = toEntity(request); + SysDepartmentEntity exists = siteMapper.selectDeptByUserName(row); + if (exists == null) { + throw new RuntimeException("成员不存在"); + } + validateSuperiorChain(row.getSite(), row.getBuNo(), row.getDepartmentId(), username, row.getSuperiorUsername()); + siteMapper.updateAccessDeptMember(row); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMember(AccessDeptMemberDeleteRequest request) { + requireDeptKey(request.getSite(), request.getBuNo(), request.getDepartmentId()); + String username = trimToNull(request.getUsername()); + if (username == null) { + throw new RuntimeException("账号不能为空"); + } + SysDepartmentEntity row = new SysDepartmentEntity(); + row.setSite(trimToNull(request.getSite())); + row.setBuNo(trimToNull(request.getBuNo())); + row.setDepartmentId(trimToNull(request.getDepartmentId())); + row.setUsername(username); + int subs = siteMapper.countDirectReportsInDept(row); + if (subs > 0) { + throw new RuntimeException("存在以该用户为上级的人员,请先调整其上级后再删除"); + } + siteMapper.deleteAccessDeptMember(row); + } + + @Override + public List listByUsername(UserAccessDeptQueryRequest request) { + String username = trimToNull(request.getUsername()); + if (username == null) { + return new ArrayList<>(); + } + SysDepartmentEntity q = new SysDepartmentEntity(); + q.setUsername(username); + List list = siteMapper.listAccessDeptByUsername(q); + return list != null ? list : new ArrayList<>(); + } + + private static void requireDeptKey(String site, String buNo, String departmentId) { + if (StringUtils.isAnyBlank(site, buNo, departmentId)) { + throw new RuntimeException("工厂、BU、部门不能为空"); + } + } + + private SysDepartmentEntity toEntity(AccessDeptMemberSaveRequest request) { + SysDepartmentEntity row = new SysDepartmentEntity(); + row.setSite(trimToNull(request.getSite())); + row.setBuNo(trimToNull(request.getBuNo())); + row.setDepartmentId(trimToNull(request.getDepartmentId())); + row.setUsername(trimToNull(request.getUsername())); + row.setJobTitle(trimToNull(request.getJobTitle())); + row.setDeptManagerFlag(normalizeManagerFlag(request.getDeptManagerFlag())); + row.setSuperiorUsername(trimToNull(request.getSuperiorUsername())); + return row; + } + + private static String normalizeManagerFlag(String flag) { + if (StringUtils.isBlank(flag)) { + return "N"; + } + String f = flag.trim(); + if ("Y".equalsIgnoreCase(f) || "1".equals(f) || "true".equalsIgnoreCase(f)) { + return "Y"; + } + return "N"; + } + + private static String trimToNull(String s) { + if (s == null) { + return null; + } + String t = s.trim(); + return t.isEmpty() ? null : t; + } + + private void validateSuperiorChain(String site, String buNo, String deptId, String memberUsername, String superiorUsername) { + if (StringUtils.isBlank(superiorUsername)) { + return; + } + String sup = superiorUsername.trim(); + if (sup.equalsIgnoreCase(memberUsername)) { + throw new RuntimeException("上级不能是自己"); + } + SysDepartmentEntity check = new SysDepartmentEntity(); + check.setSite(site); + check.setBuNo(buNo); + check.setDepartmentId(deptId); + check.setUsername(sup); + if (siteMapper.countMemberInDept(check) == 0) { + throw new RuntimeException("上级必须是本部门已有成员"); + } + String current = sup; + for (int i = 0; i < 64; i++) { + if (current != null && current.equalsIgnoreCase(memberUsername)) { + throw new RuntimeException("上级关系不能形成环路"); + } + if (current == null) { + break; + } + check.setUsername(current); + String next = siteMapper.selectSuperiorUsernameInDept(check); + if (StringUtils.isBlank(next)) { + break; + } + current = next.trim(); + } + } +} diff --git a/src/main/java/com/xujie/modules/sys/entity/SysDepartmentEntity.java b/src/main/java/com/xujie/modules/sys/entity/SysDepartmentEntity.java index 02bad98..5b3ff84 100644 --- a/src/main/java/com/xujie/modules/sys/entity/SysDepartmentEntity.java +++ b/src/main/java/com/xujie/modules/sys/entity/SysDepartmentEntity.java @@ -43,8 +43,45 @@ public class SysDepartmentEntity extends QueryPage { */ private String buDesc; + /** + * 部门内职称(Access_dept.job_title) + */ + private String jobTitle; + /** + * 是否部门经理 Y/N(Access_dept.dept_manager_flag) + */ + private String deptManagerFlag; + /** + * 同部门内直属上级账号(Access_dept.superior_username) + */ + private String superiorUsername; + private List deptList; + public String getJobTitle() { + return jobTitle; + } + + public void setJobTitle(String jobTitle) { + this.jobTitle = jobTitle; + } + + public String getDeptManagerFlag() { + return deptManagerFlag; + } + + public void setDeptManagerFlag(String deptManagerFlag) { + this.deptManagerFlag = deptManagerFlag; + } + + public String getSuperiorUsername() { + return superiorUsername; + } + + public void setSuperiorUsername(String superiorUsername) { + this.superiorUsername = superiorUsername; + } + public List getDeptList() { return deptList; } diff --git a/src/main/resources/mapper/factory/SiteMapper.xml b/src/main/resources/mapper/factory/SiteMapper.xml index 6da1622..cc64820 100644 --- a/src/main/resources/mapper/factory/SiteMapper.xml +++ b/src/main/resources/mapper/factory/SiteMapper.xml @@ -454,4 +454,77 @@ - \ No newline at end of file + + + + + + INSERT INTO Access_dept (site, bu_no, department_id, username, job_title, dept_manager_flag, superior_username) + VALUES (#{site}, #{buNo}, #{departmentId}, #{username}, #{jobTitle}, #{deptManagerFlag}, #{superiorUsername}) + + + + UPDATE Access_dept + SET job_title = #{jobTitle}, + dept_manager_flag = #{deptManagerFlag}, + superior_username = #{superiorUsername} + WHERE site = #{site} AND bu_no = #{buNo} AND department_id = #{departmentId} AND username = #{username} + + + + + + DELETE FROM Access_dept + WHERE site = #{site} AND bu_no = #{buNo} AND department_id = #{departmentId} AND username = #{username} + + + + + + + + + diff --git a/src/main/resources/mapper/sys/SysDepartmentMapper.xml b/src/main/resources/mapper/sys/SysDepartmentMapper.xml index 73aa7bc..da3eabe 100644 --- a/src/main/resources/mapper/sys/SysDepartmentMapper.xml +++ b/src/main/resources/mapper/sys/SysDepartmentMapper.xml @@ -26,6 +26,8 @@ AND department_name like '%' + #{query.departmentName} + '%' + order by department_id +