实现单用户多部门支持:创建中间表、实体类、Mapper和多部门操作方法,修改钉钉登录逻辑支持匹配多个部门
This commit is contained in:
parent
f36ec495a2
commit
9dc5b1d9ee
@ -0,0 +1,49 @@
|
||||
package com.designhub.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户部门关联实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_department")
|
||||
public class UserDepartment implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 是否为主部门:0-否,1-是
|
||||
*/
|
||||
private Integer isPrimary;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.designhub.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.designhub.entity.UserDepartment;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 用户部门关联Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserDepartmentMapper extends BaseMapper<UserDepartment> {
|
||||
}
|
||||
@ -7,13 +7,16 @@ import com.designhub.dto.LoginDTO;
|
||||
import com.designhub.dto.RegisterDTO;
|
||||
import com.designhub.entity.Department;
|
||||
import com.designhub.entity.User;
|
||||
import com.designhub.entity.UserDepartment;
|
||||
import com.designhub.exception.BusinessException;
|
||||
import com.designhub.mapper.UserMapper;
|
||||
import com.designhub.mapper.DepartmentMapper;
|
||||
import com.designhub.mapper.UserDepartmentMapper;
|
||||
import com.designhub.common.ResultCode;
|
||||
import com.designhub.util.JwtUtil;
|
||||
import com.designhub.vo.LoginVO;
|
||||
import com.designhub.vo.UserInfoVO;
|
||||
import com.designhub.vo.UserDepartmentVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
@ -25,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -37,6 +41,7 @@ public class UserService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final DepartmentMapper departmentMapper;
|
||||
private final UserDepartmentMapper userDepartmentMapper;
|
||||
private final TeamScorePoolService teamScorePoolService;
|
||||
private final RoleService roleService;
|
||||
private final DingTalkService dingTalkService;
|
||||
@ -487,73 +492,52 @@ public class UserService {
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
// 3. 检查部门是否需要更新
|
||||
// 3. 同步部门(支持多部门)
|
||||
if (dingDepartments != null && !dingDepartments.isEmpty()) {
|
||||
if (user.getDeptId() != null) {
|
||||
// 用户已有部门:检查是否需要更新
|
||||
Department currentDept = departmentMapper.selectById(user.getDeptId());
|
||||
if (currentDept != null && StringUtils.hasText(currentDept.getDingDeptId())) {
|
||||
// 检查用户是否还在原部门
|
||||
boolean stillInDept = dingDepartments.stream()
|
||||
.anyMatch(d -> currentDept.getDingDeptId().equals(d.get("dept_id").toString()));
|
||||
// 匹配多个部门
|
||||
List<Long> matchedDeptIds = matchSystemDepartments(dingDepartments);
|
||||
|
||||
if (!stillInDept) {
|
||||
String newDeptNames = dingDepartments.stream()
|
||||
.map(d -> String.valueOf(d.get("name")))
|
||||
.collect(Collectors.joining(","));
|
||||
log.warn("用户钉钉部门已变化: userId={}, 原部门={}, 钉钉部门={}",
|
||||
user.getId(), currentDept.getDeptName(), newDeptNames);
|
||||
if (!matchedDeptIds.isEmpty()) {
|
||||
// 同步多个部门到sys_user_department表
|
||||
// 第一个匹配的部门作为主部门
|
||||
Long primaryDeptId = matchedDeptIds.get(0);
|
||||
setUserDepartments(user.getId(), matchedDeptIds, primaryDeptId);
|
||||
|
||||
// 尝试重新匹配部门
|
||||
Long newDeptId = matchSystemDepartment(dingDepartments);
|
||||
if (newDeptId != null && !newDeptId.equals(user.getDeptId())) {
|
||||
Department newDept = departmentMapper.selectById(newDeptId);
|
||||
user.setDeptId(newDeptId);
|
||||
user.setDeptName(newDept.getDeptName());
|
||||
// 根据部门类型设置角色
|
||||
user.setRoleIds("receiving".equals(newDept.getDeptType()) ? "5" : "6");
|
||||
user.setStatus(1); // 启用用户
|
||||
needUpdate = true;
|
||||
log.info("自动同步到新部门: userId={}, 新部门={}",
|
||||
user.getId(), newDept.getDeptName());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 用户没有部门:尝试匹配部门
|
||||
Long matchedDeptId = matchSystemDepartment(dingDepartments);
|
||||
if (matchedDeptId != null) {
|
||||
Department dept = departmentMapper.selectById(matchedDeptId);
|
||||
user.setDeptId(matchedDeptId);
|
||||
user.setDeptName(dept.getDeptName());
|
||||
user.setRoleIds("receiving".equals(dept.getDeptType()) ? "5" : "6");
|
||||
// 更新sys_user表的主部门(向后兼容)
|
||||
Department primaryDept = departmentMapper.selectById(primaryDeptId);
|
||||
if (primaryDept != null) {
|
||||
user.setDeptId(primaryDeptId);
|
||||
user.setDeptName(primaryDept.getDeptName());
|
||||
// 根据主部门类型设置角色
|
||||
user.setRoleIds("receiving".equals(primaryDept.getDeptType()) ? "5" : "6");
|
||||
user.setStatus(1); // 启用用户
|
||||
needUpdate = true;
|
||||
log.info("已有用户匹配到部门: userId={}, deptId={}, deptName={}",
|
||||
user.getId(), matchedDeptId, dept.getDeptName());
|
||||
} else {
|
||||
// 无法匹配,使用第一个可用部门作为默认值
|
||||
List<Department> availableDepts = departmentMapper.selectList(
|
||||
new LambdaQueryWrapper<Department>()
|
||||
.eq(Department::getStatus, 1)
|
||||
.eq(Department::getDeleted, 0)
|
||||
.orderByAsc(Department::getSortOrder)
|
||||
.orderByAsc(Department::getId)
|
||||
);
|
||||
log.info("同步用户多个部门: userId={}, 部门数量={}, 主部门={}",
|
||||
user.getId(), matchedDeptIds.size(), primaryDept.getDeptName());
|
||||
}
|
||||
} else {
|
||||
// 无法匹配,使用第一个可用部门作为默认值
|
||||
List<Department> availableDepts = departmentMapper.selectList(
|
||||
new LambdaQueryWrapper<Department>()
|
||||
.eq(Department::getStatus, 1)
|
||||
.eq(Department::getDeleted, 0)
|
||||
.orderByAsc(Department::getSortOrder)
|
||||
.orderByAsc(Department::getId)
|
||||
);
|
||||
|
||||
if (!availableDepts.isEmpty()) {
|
||||
Department defaultDept = availableDepts.get(0);
|
||||
user.setDeptId(defaultDept.getId());
|
||||
user.setDeptName(defaultDept.getDeptName());
|
||||
user.setRoleIds("receiving".equals(defaultDept.getDeptType()) ? "5" : "6");
|
||||
user.setStatus(1); // 启用用户
|
||||
needUpdate = true;
|
||||
log.warn("已有用户无法匹配,使用默认部门: userId={}, deptId={}, deptName={}, 钉钉部门: {}",
|
||||
user.getId(), defaultDept.getId(), defaultDept.getDeptName(),
|
||||
dingDepartments.stream()
|
||||
.map(d -> String.valueOf(d.get("name")))
|
||||
.collect(Collectors.joining(", ")));
|
||||
}
|
||||
if (!availableDepts.isEmpty()) {
|
||||
Department defaultDept = availableDepts.get(0);
|
||||
setUserDepartments(user.getId(), List.of(defaultDept.getId()), defaultDept.getId());
|
||||
user.setDeptId(defaultDept.getId());
|
||||
user.setDeptName(defaultDept.getDeptName());
|
||||
user.setRoleIds("receiving".equals(defaultDept.getDeptType()) ? "5" : "6");
|
||||
user.setStatus(1); // 启用用户
|
||||
needUpdate = true;
|
||||
log.warn("已有用户无法匹配,使用默认部门: userId={}, deptId={}, deptName={}, 钉钉部门: {}",
|
||||
user.getId(), defaultDept.getId(), defaultDept.getDeptName(),
|
||||
dingDepartments.stream()
|
||||
.map(d -> String.valueOf(d.get("name")))
|
||||
.collect(Collectors.joining(", ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -624,8 +608,8 @@ public class UserService {
|
||||
// 需要用户手动选择部门类型和具体部门
|
||||
log.info("钉钉用户首次登录,创建临时账号: email={}", email);
|
||||
|
||||
// 尝试匹配系统部门
|
||||
Long matchedDeptId = matchSystemDepartment(dingDepartments);
|
||||
// 尝试匹配系统部门(支持多部门)
|
||||
List<Long> matchedDeptIds = matchSystemDepartments(dingDepartments);
|
||||
String username = detailedInfo != null && detailedInfo.get("job_number") != null
|
||||
? (String) detailedInfo.get("job_number") : "DT_" + unionId.substring(0, 8);
|
||||
|
||||
@ -642,15 +626,16 @@ public class UserService {
|
||||
user.setStatus(1);
|
||||
user.setDeleted(0);
|
||||
|
||||
if (matchedDeptId != null) {
|
||||
// 自动匹配到部门
|
||||
Department dept = departmentMapper.selectById(matchedDeptId);
|
||||
user.setDeptId(matchedDeptId);
|
||||
user.setDeptName(dept.getDeptName());
|
||||
// 根据部门类型设置默认角色
|
||||
user.setRoleIds("receiving".equals(dept.getDeptType()) ? "5" : "6");
|
||||
log.info("自动匹配到系统部门: deptId={}, deptName={}, type={}",
|
||||
matchedDeptId, dept.getDeptName(), dept.getDeptType());
|
||||
if (!matchedDeptIds.isEmpty()) {
|
||||
// 自动匹配到多个部门,第一个作为主部门
|
||||
Long primaryDeptId = matchedDeptIds.get(0);
|
||||
Department primaryDept = departmentMapper.selectById(primaryDeptId);
|
||||
user.setDeptId(primaryDeptId);
|
||||
user.setDeptName(primaryDept.getDeptName());
|
||||
// 根据主部门类型设置默认角色
|
||||
user.setRoleIds("receiving".equals(primaryDept.getDeptType()) ? "5" : "6");
|
||||
log.info("自动匹配到系统部门(多部门): userId={}, 部门数量={}, 主部门={}",
|
||||
username, matchedDeptIds.size(), primaryDept.getDeptName());
|
||||
} else {
|
||||
// 无法自动匹配,使用第一个可用部门作为默认值
|
||||
List<Department> availableDepts = departmentMapper.selectList(
|
||||
@ -667,6 +652,7 @@ public class UserService {
|
||||
user.setDeptId(defaultDept.getId());
|
||||
user.setDeptName(defaultDept.getDeptName());
|
||||
user.setRoleIds("receiving".equals(defaultDept.getDeptType()) ? "5" : "6");
|
||||
matchedDeptIds = List.of(defaultDept.getId());
|
||||
log.warn("无法自动匹配系统部门,使用默认部门: deptId={}, deptName={}, 钉钉部门: {}",
|
||||
defaultDept.getId(), defaultDept.getDeptName(),
|
||||
dingDepartments.stream()
|
||||
@ -686,6 +672,12 @@ public class UserService {
|
||||
}
|
||||
|
||||
userMapper.insert(user);
|
||||
|
||||
// 同步多个部门到sys_user_department表
|
||||
if (!matchedDeptIds.isEmpty()) {
|
||||
Long primaryDeptId = matchedDeptIds.get(0);
|
||||
setUserDepartments(user.getId(), matchedDeptIds, primaryDeptId);
|
||||
}
|
||||
log.info("钉钉用户创建成功: userId={}, username={}, needSelectDept={}",
|
||||
user.getId(), user.getUsername(), matchedDeptId == null);
|
||||
|
||||
@ -861,6 +853,43 @@ public class UserService {
|
||||
log.warn("检查部门负责人状态失败: userId={}, error={}", user.getId(), e.getMessage());
|
||||
}
|
||||
|
||||
// 获取用户的所有部门列表
|
||||
List<UserDepartmentVO> departments = List.of();
|
||||
try {
|
||||
List<UserDepartment> userDepts = userDepartmentMapper.selectList(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, user.getId())
|
||||
);
|
||||
|
||||
if (!userDepts.isEmpty()) {
|
||||
List<Long> deptIds = userDepts.stream()
|
||||
.map(UserDepartment::getDeptId)
|
||||
.collect(Collectors.toList());
|
||||
List<Department> depts = departmentMapper.selectBatchIds(deptIds);
|
||||
|
||||
// 构建部门VO列表,保持isPrimary顺序
|
||||
Map<Long, Department> deptMap = depts.stream()
|
||||
.collect(Collectors.toMap(Department::getId, d -> d));
|
||||
|
||||
departments = userDepts.stream()
|
||||
.map(ud -> {
|
||||
Department dept = deptMap.get(ud.getDeptId());
|
||||
if (dept != null) {
|
||||
return UserDepartmentVO.builder()
|
||||
.deptId(dept.getId())
|
||||
.deptName(dept.getDeptName())
|
||||
.isPrimary(ud.getIsPrimary())
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(d -> d != null)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取用户部门列表失败: userId={}, error={}", user.getId(), e.getMessage());
|
||||
}
|
||||
|
||||
UserInfoVO userInfoVO = UserInfoVO.builder()
|
||||
.id(user.getId())
|
||||
.username(user.getUsername())
|
||||
@ -870,6 +899,7 @@ public class UserService {
|
||||
.avatar(user.getAvatar())
|
||||
.deptId(user.getDeptId())
|
||||
.deptName(user.getDeptName())
|
||||
.departments(departments)
|
||||
.roleIds(user.getRoleIds())
|
||||
.roles(roleCodes)
|
||||
.status(user.getStatus())
|
||||
@ -918,4 +948,217 @@ public class UserService {
|
||||
.roleIds(user.getRoleIds())
|
||||
.build();
|
||||
}
|
||||
|
||||
// ==================== 多部门支持方法 ====================
|
||||
|
||||
/**
|
||||
* 获取用户的所有部门ID列表
|
||||
*/
|
||||
public List<Long> getUserDepartmentIds(Long userId) {
|
||||
List<UserDepartment> userDepts = userDepartmentMapper.selectList(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
);
|
||||
return userDepts.stream()
|
||||
.map(UserDepartment::getDeptId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的所有部门信息
|
||||
*/
|
||||
public List<Department> getUserDepartments(Long userId) {
|
||||
List<Long> deptIds = getUserDepartmentIds(userId);
|
||||
if (deptIds.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return departmentMapper.selectBatchIds(deptIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户到部门(如果不存在则添加)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addUserToDepartment(Long userId, Long deptId, boolean isPrimary) {
|
||||
// 检查是否已存在
|
||||
UserDepartment exist = userDepartmentMapper.selectOne(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
.eq(UserDepartment::getDeptId, deptId)
|
||||
);
|
||||
|
||||
if (exist == null) {
|
||||
UserDepartment userDept = new UserDepartment();
|
||||
userDept.setUserId(userId);
|
||||
userDept.setDeptId(deptId);
|
||||
userDept.setIsPrimary(isPrimary ? 1 : 0);
|
||||
userDepartmentMapper.insert(userDept);
|
||||
log.info("添加用户到部门: userId={}, deptId={}, isPrimary={}", userId, deptId, isPrimary);
|
||||
} else if (isPrimary && exist.getIsPrimary() == 0) {
|
||||
// 更新为主部门
|
||||
exist.setIsPrimary(1);
|
||||
userDepartmentMapper.updateById(exist);
|
||||
log.info("设置为主部门: userId={}, deptId={}", userId, deptId);
|
||||
}
|
||||
|
||||
// 如果设置为主部门,需要更新sys_user表的dept_id
|
||||
if (isPrimary) {
|
||||
Department dept = departmentMapper.selectById(deptId);
|
||||
if (dept != null) {
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user != null) {
|
||||
user.setDeptId(deptId);
|
||||
user.setDeptName(dept.getDeptName());
|
||||
userMapper.updateById(user);
|
||||
}
|
||||
}
|
||||
|
||||
// 将其他部门设置为非主部门
|
||||
userDepartmentMapper.update(null,
|
||||
new LambdaUpdateWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
.ne(UserDepartment::getDeptId, deptId)
|
||||
.set(UserDepartment::getIsPrimary, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从部门中移除用户
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removeUserFromDepartment(Long userId, Long deptId) {
|
||||
// 检查是否为主部门
|
||||
UserDepartment userDept = userDepartmentMapper.selectOne(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
.eq(UserDepartment::getDeptId, deptId)
|
||||
);
|
||||
|
||||
if (userDept != null && userDept.getIsPrimary() == 1) {
|
||||
// 如果是主部门,需要设置另一个部门为主部门,或清空主部门
|
||||
List<UserDepartment> otherDepts = userDepartmentMapper.selectList(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
.ne(UserDepartment::getDeptId, deptId)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
|
||||
if (!otherDepts.isEmpty()) {
|
||||
// 设置第一个其他部门为主部门
|
||||
UserDepartment newPrimary = otherDepts.get(0);
|
||||
newPrimary.setIsPrimary(1);
|
||||
userDepartmentMapper.updateById(newPrimary);
|
||||
|
||||
Department newDept = departmentMapper.selectById(newPrimary.getDeptId());
|
||||
if (newDept != null) {
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user != null) {
|
||||
user.setDeptId(newDept.getId());
|
||||
user.setDeptName(newDept.getDeptName());
|
||||
userMapper.updateById(user);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有其他部门,清空主部门
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user != null) {
|
||||
user.setDeptId(null);
|
||||
user.setDeptName(null);
|
||||
userMapper.updateById(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除关联
|
||||
userDepartmentMapper.delete(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
.eq(UserDepartment::getDeptId, deptId)
|
||||
);
|
||||
log.info("从部门移除用户: userId={}, deptId={}", userId, deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户的部门列表(替换现有部门)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void setUserDepartments(Long userId, List<Long> deptIds, Long primaryDeptId) {
|
||||
// 删除所有现有关联
|
||||
userDepartmentMapper.delete(
|
||||
new LambdaQueryWrapper<UserDepartment>()
|
||||
.eq(UserDepartment::getUserId, userId)
|
||||
);
|
||||
|
||||
// 添加新关联
|
||||
if (deptIds != null && !deptIds.isEmpty()) {
|
||||
for (Long deptId : deptIds) {
|
||||
boolean isPrimary = deptId.equals(primaryDeptId);
|
||||
addUserToDepartment(userId, deptId, isPrimary);
|
||||
}
|
||||
} else {
|
||||
// 清空部门
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user != null) {
|
||||
user.setDeptId(null);
|
||||
user.setDeptName(null);
|
||||
userMapper.updateById(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配多个系统部门(根据钉钉部门列表)
|
||||
*/
|
||||
private List<Long> matchSystemDepartments(List<Map<String, Object>> dingDepartments) {
|
||||
if (dingDepartments == null || dingDepartments.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
// 获取所有系统部门
|
||||
List<Department> systemDepts = departmentMapper.selectList(
|
||||
new LambdaQueryWrapper<Department>()
|
||||
.eq(Department::getStatus, 1)
|
||||
.eq(Department::getDeleted, 0)
|
||||
);
|
||||
|
||||
List<Long> matchedDeptIds = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> dingDept : dingDepartments) {
|
||||
String dingDeptName = (String) dingDept.get("name");
|
||||
Object dingDeptIdObj = dingDept.get("dept_id");
|
||||
String dingDeptId = dingDeptIdObj != null ? dingDeptIdObj.toString() : null;
|
||||
|
||||
Department matched = null;
|
||||
|
||||
// 1. 优先通过钉钉部门ID精确匹配
|
||||
if (dingDeptId != null) {
|
||||
matched = systemDepts.stream()
|
||||
.filter(d -> dingDeptId.equals(d.getDingDeptId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (matched != null) {
|
||||
log.info("通过钉钉部门ID精确匹配: {} -> {}", dingDeptId, matched.getDeptName());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 通过部门名称模糊匹配
|
||||
if (matched == null && dingDeptName != null) {
|
||||
matched = systemDepts.stream()
|
||||
.filter(d -> d.getDeptName().contains(dingDeptName) ||
|
||||
dingDeptName.contains(d.getDeptName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (matched != null) {
|
||||
log.info("通过部门名称模糊匹配: {} -> {}", dingDeptName, matched.getDeptName());
|
||||
}
|
||||
}
|
||||
|
||||
if (matched != null && !matchedDeptIds.contains(matched.getId())) {
|
||||
matchedDeptIds.add(matched.getId());
|
||||
}
|
||||
}
|
||||
|
||||
return matchedDeptIds;
|
||||
}
|
||||
}
|
||||
|
||||
26
backend/src/main/java/com/designhub/vo/UserDepartmentVO.java
Normal file
26
backend/src/main/java/com/designhub/vo/UserDepartmentVO.java
Normal file
@ -0,0 +1,26 @@
|
||||
package com.designhub.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Builder;
|
||||
|
||||
/**
|
||||
* 用户部门信息VO
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class UserDepartmentVO {
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 是否为主部门:0-否,1-是
|
||||
*/
|
||||
private Integer isPrimary;
|
||||
}
|
||||
@ -42,15 +42,20 @@ public class UserInfoVO {
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
* 部门ID(主部门,向后兼容)
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
* 部门名称(主部门,向后兼容)
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 用户的所有部门列表(多部门支持)
|
||||
*/
|
||||
private List<UserDepartmentVO> departments;
|
||||
|
||||
/**
|
||||
* 角色ID列表(逗号分隔)
|
||||
*/
|
||||
|
||||
25
database/add_user_department_table.sql
Normal file
25
database/add_user_department_table.sql
Normal file
@ -0,0 +1,25 @@
|
||||
-- 用户部门关联表(支持多部门)
|
||||
-- 创建时间: 2026-01-02
|
||||
-- 说明: 支持单用户属于多个部门
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sys_user_department` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` BIGINT NOT NULL COMMENT '用户ID',
|
||||
`dept_id` BIGINT NOT NULL COMMENT '部门ID',
|
||||
`is_primary` TINYINT DEFAULT 0 COMMENT '是否为主部门:0-否,1-是',
|
||||
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_dept` (`user_id`, `dept_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_dept_id` (`dept_id`),
|
||||
CONSTRAINT `fk_user_dept_user` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_user_dept_dept` FOREIGN KEY (`dept_id`) REFERENCES `sys_dept` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户部门关联表';
|
||||
|
||||
-- 数据迁移:将现有sys_user表中的dept_id迁移到sys_user_department表
|
||||
INSERT INTO `sys_user_department` (`user_id`, `dept_id`, `is_primary`)
|
||||
SELECT `id`, `dept_id`, 1
|
||||
FROM `sys_user`
|
||||
WHERE `dept_id` IS NOT NULL AND `dept_id` > 0
|
||||
ON DUPLICATE KEY UPDATE `is_primary` = 1;
|
||||
89
deploy_from_git.sh
Executable file
89
deploy_from_git.sh
Executable file
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# 从Git拉取代码并部署到服务器
|
||||
# 服务器: 45.192.99.48
|
||||
###############################################################################
|
||||
|
||||
SERVER_IP="45.192.99.48"
|
||||
SERVER_USER="root"
|
||||
SERVER_PASSWORD="1blZllMIp7"
|
||||
APP_DIR="/opt/designhub"
|
||||
GIT_REPO="http://chenpei:jsjj654321@git.1080p.hk/chenpei/qiangdanxitong.git"
|
||||
|
||||
# 颜色定义
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo "========================================"
|
||||
echo -e "${GREEN}从Git拉取代码并部署${NC}"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "服务器: ${SERVER_IP}"
|
||||
echo "Git仓库: ${GIT_REPO}"
|
||||
echo ""
|
||||
|
||||
# 检查sshpass
|
||||
if ! command -v sshpass &> /dev/null; then
|
||||
echo "正在安装sshpass..."
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
brew install hudochenkov/sshpass/sshpass 2>/dev/null || {
|
||||
echo -e "${RED}请先安装sshpass: brew install hudochenkov/sshpass/sshpass${NC}"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# 在服务器上执行部署
|
||||
sshpass -p "${SERVER_PASSWORD}" ssh -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} << ENDSSH
|
||||
set -e
|
||||
|
||||
echo -e "${BLUE}[1/6] 检查Git仓库...${NC}"
|
||||
cd ${APP_DIR}
|
||||
|
||||
if [ ! -d ".git" ]; then
|
||||
echo "初始化Git仓库..."
|
||||
# 先暂存现有文件
|
||||
git init
|
||||
git remote add origin ${GIT_REPO} 2>/dev/null || git remote set-url origin ${GIT_REPO}
|
||||
# 添加现有文件到Git
|
||||
git add -A 2>/dev/null || true
|
||||
git commit -m "Backup existing files" 2>/dev/null || true
|
||||
# 拉取最新代码(允许合并)
|
||||
git pull origin main --allow-unrelated-histories || git fetch origin main:main && git checkout main
|
||||
else
|
||||
echo "拉取最新代码..."
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[2/6] 备份当前JAR文件...${NC}"
|
||||
if [ -f "${APP_DIR}/designhub.jar" ]; then
|
||||
cp ${APP_DIR}/designhub.jar ${APP_DIR}/designhub.jar.backup.\$(date +%Y%m%d_%H%M%S) || true
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[3/6] 构建后端...${NC}"
|
||||
cd ${APP_DIR}/backend
|
||||
mvn clean package -DskipTests
|
||||
|
||||
echo -e "${BLUE}[4/6] 复制JAR文件...${NC}"
|
||||
cp target/designhub-backend-1.0.0.jar ${APP_DIR}/designhub.jar
|
||||
|
||||
echo -e "${BLUE}[5/6] 重启服务...${NC}"
|
||||
systemctl restart designhub
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}等待服务启动...${NC}"
|
||||
sleep 5
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}[6/6] 检查服务状态...${NC}"
|
||||
systemctl status designhub --no-pager | head -15
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 部署完成!${NC}"
|
||||
ENDSSH
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 部署脚本执行完成!${NC}"
|
||||
35
服务器部署命令.txt
Normal file
35
服务器部署命令.txt
Normal file
@ -0,0 +1,35 @@
|
||||
# 在服务器上执行以下命令部署最新代码
|
||||
|
||||
# 1. 连接到服务器
|
||||
ssh root@45.192.99.48
|
||||
# 密码: 1blZllMIp7
|
||||
|
||||
# 2. 进入项目目录
|
||||
cd /opt/designhub
|
||||
|
||||
# 3. 如果还没有Git仓库,先初始化
|
||||
if [ ! -d ".git" ]; then
|
||||
git init
|
||||
git remote add origin http://chenpei:jsjj654321@git.1080p.hk/chenpei/qiangdanxitong.git
|
||||
git fetch origin
|
||||
git checkout -b main origin/main
|
||||
else
|
||||
# 拉取最新代码
|
||||
git pull origin main
|
||||
fi
|
||||
|
||||
# 4. 构建后端
|
||||
cd backend
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 5. 复制JAR文件
|
||||
cp target/designhub-backend-1.0.0.jar /opt/designhub/designhub.jar
|
||||
|
||||
# 6. 重启服务
|
||||
systemctl restart designhub
|
||||
|
||||
# 7. 检查服务状态
|
||||
systemctl status designhub
|
||||
|
||||
# 8. 查看日志(可选)
|
||||
tail -f /opt/designhub/logs/application.log
|
||||
Loading…
x
Reference in New Issue
Block a user