This commit is contained in:
zjf committed 2026-11-04 14:54:30 +08:00
1 parent 55f9cd4148
commit 47a4e4d7de
1 file changed
+45 -17
@@ -1,8 +1,11 @@
package com.bsd.pjcloud.supermarket.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
import com.bsd.pjcloud.admin.api.entity.SysDept;
import com.bsd.pjcloud.admin.api.feign.RemoteDeptService;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.common.core.constant.CommonRoleConstant;
import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
@@ -18,40 +21,48 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 酒店管理数据隔离(防水平/垂直越权):
* 酒店管理数据隔离(移动端/PC 管理端共用):
* <ul>
* <li>垂直:接口 {@code @PreAuthorize} 酒店权限</li>
* <li>水平:从登录用户部门向上查找酒店类型商户;仅可见该商户绑定部门下的酒店</li>
* <li>找不到酒店商户 → 无数据;dept_id 为空 → 非超管不可见</li>
* <li>ROLE_ADMIN 可看全部:以<strong>用户中心最新角色</strong>为准,避免 Token 未刷新仍按超管放开</li>
* <li>水平:本部门及下级(上级管下级);下级看不到上级部门酒店</li>
* <li>dept_id 为空 → 非超管不可见</li>
* <li>ROLE_ADMIN 可看全部:以用户中心最新角色为准</li>
* </ul>
* <p>「向上找酒店商户」{@link #resolveHotelMerchantDeptId()} 仍保留,供归属解析等场景使用,不作为列表隔离条件。
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class SmHotelMerchantScopeHelper {
private final RemoteMchService remoteMchService;
private final RemoteDeptService remoteDeptService;
private final RemoteUserService remoteUserService;
private final RemoteMchService remoteMchService;
/**
* @return null=平台超管不限制;empty=无酒店商户;单元素=商户绑定部门
* @return null=平台超管不限制;empty=无部门/无范围;非空=本部门及下级 deptId
*/
public List<Long> resolveHotelDeptScope() {
if (isPlatformAdmin()) {
return null;
}
Long merchantDeptId = resolveHotelMerchantDeptId();
if (merchantDeptId == null) {
PjcloudUser user = SecurityUtils.getUser();
if (user == null || user.getDeptId() == null) {
return List.of();
}
return List.of(merchantDeptId);
return listSelfAndDescendantDeptIds(user.getDeptId());
}
/** 用户部门 → 视图向上解析最近的酒店商户 → 商户绑定 dept_id */
/**
* 用户部门 → 视图向上解析最近的酒店商户 → 商户绑定 dept_id。
* <p>支付/归属解析沿用;管理端列表隔离请用 {@link #resolveHotelDeptScope()}。
*/
public Long resolveHotelMerchantDeptId() {
PjcloudUser user = SecurityUtils.getUser();
if (user == null || user.getDeptId() == null) {
@@ -70,6 +81,27 @@ public class SmHotelMerchantScopeHelper {
return null;
}
/** 本部门 + 下级部门(含自身)。失败时退化为仅本部门。 */
private List<Long> listSelfAndDescendantDeptIds(Long rootDeptId) {
try {
R<List<SysDept>> deptR = remoteDeptService.getDescendantList(rootDeptId);
if (deptR != null && deptR.isOk() && CollUtil.isNotEmpty(deptR.getData())) {
List<Long> ids = deptR.getData().stream()
.map(SysDept::getDeptId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(ids)) {
return ids;
}
}
}
catch (Exception e) {
log.warn("解析本部门及下级失败, deptId={}", rootDeptId, e);
}
return List.of(rootDeptId);
}
public void applyDeptScope(LambdaQueryWrapper<SmHotelEntity> wrapper) {
if (wrapper == null) {
return;
@@ -99,18 +131,14 @@ public class SmHotelMerchantScopeHelper {
return deptIds.contains(hotel.getDeptId());
}
/** 新建酒店默认归属:当前用户本部门 */
public Long resolveDefaultHotelDeptId() {
List<Long> deptIds = resolveHotelDeptScope();
if (deptIds == null) {
PjcloudUser user = SecurityUtils.getUser();
return user == null ? null : user.getDeptId();
}
return deptIds.isEmpty() ? null : deptIds.get(0);
PjcloudUser user = SecurityUtils.getUser();
return user == null ? null : user.getDeptId();
}
/**
* 是否平台超管:查 UPMS 最新 roleCodes,不信任 JWT 里残留的 ROLE_{id}。
* 去掉超管后未重新登录时,仍按普通账号做商户隔离。
*/
private boolean isPlatformAdmin() {
PjcloudUser user = SecurityUtils.getUser();