@@ -0,0 +1,24 @@
|
||||
package com.yunhai.userhome.service;
|
||||
|
||||
import com.yunhai.platform.utils.model.BoaApp;
|
||||
import com.yunhai.platform.utils.model.BoaAppType;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 远程「用户可访问应用」数据服务(跨仓 UserBase)。
|
||||
*
|
||||
* <p>实现 {@link com.yunhai.userhome.service.impl.OpenApiAppRemoteServiceImpl}
|
||||
* 经 {@code YschBaseOpenApi.getUserApp} 实时拉取(自动带 yh-app-auth 签名),
|
||||
* 数据权威在 UserBase;本模块不冗余应用元数据。</p>
|
||||
*/
|
||||
public interface AppRemoteService {
|
||||
|
||||
/** 取当前用户可访问的应用全集(按应用类型分组,BoaAppType.id/name/apps)。 */
|
||||
List<BoaAppType> getUserApps(BoaUser user);
|
||||
|
||||
/** 按应用ID取单个应用(在已拉取的全集中查找,避免额外跨仓请求)。 */
|
||||
Optional<BoaApp> getAppById(BoaUser user, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.yunhai.userhome.service;
|
||||
|
||||
import com.yunhai.userhome.entity.UserCurrentRole;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户当前激活角色(user_current_role 表读写)。
|
||||
*/
|
||||
public interface IUserCurrentRoleService {
|
||||
|
||||
/** 取用户当前角色(可能不存在)。 */
|
||||
Optional<UserCurrentRole> findById(Integer userId);
|
||||
|
||||
/** 保存/覆盖用户当前角色。 */
|
||||
void save(UserCurrentRole role);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.yunhai.userhome.service;
|
||||
|
||||
import com.yunhai.platform.utils.model.BoaApp;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import com.yunhai.userhome.entity.UsedApp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 本地「常用应用」服务(used_app 表读写,对齐旧 UserHome 四维结构)。
|
||||
*/
|
||||
public interface UsedAppService {
|
||||
|
||||
/** 覆盖式保存(同 setId+type+roleType+schId 唯一,存在则更新)。 */
|
||||
void save(UsedApp usedApp);
|
||||
|
||||
/**
|
||||
* 按「学校+用户+角色」取生效的常用设置(多级:用户 > 学校 > 系统;schId==uid 直接取学校级)。
|
||||
*
|
||||
* @param schId 学校ID(0 时按用户主学校推断后由调用方处理)
|
||||
* @param uid 用户ID(isSch 时为 schId)
|
||||
* @param roleType 角色类型(用户级 -1)
|
||||
*/
|
||||
Optional<UsedApp> findById(Integer schId, Integer uid, Integer roleType);
|
||||
|
||||
/** 取常用应用详情列表(BoaApp,按 appIds 顺序从可访问全集过滤)。 */
|
||||
List<BoaApp> getUsedAppList(Integer schId, Integer uid, Integer roleType, BoaUser user);
|
||||
|
||||
/** 用户级保存(type=USER, roleType=-1)。 */
|
||||
void saveUserId(UsedApp usedApp);
|
||||
|
||||
/** 用户级常用(type=USER, roleType=-1)。 */
|
||||
Optional<UsedApp> findByUserId(Integer uid);
|
||||
|
||||
/** 常用应用精简映射(id/name/icon/url),用于 getUsedAppById / getAppByIds。 */
|
||||
List<Map<String, Object>> getUsedAppMapList(BoaUser user, Integer uid);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.yunhai.userhome.service.impl;
|
||||
|
||||
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
|
||||
import com.yunhai.platform.utils.enums.ClientEnum;
|
||||
import com.yunhai.platform.utils.model.BoaApp;
|
||||
import com.yunhai.platform.utils.model.BoaAppType;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import com.yunhai.userhome.service.AppRemoteService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@link AppRemoteService} 真实实现:经 yh-platform {@code YschBaseOpenApi} 调 UserBase
|
||||
* {@code GET /oapi/app/list?userId=&clientType=}(自动带 app-auth 签名)。
|
||||
*/
|
||||
@Service
|
||||
public class OpenApiAppRemoteServiceImpl implements AppRemoteService {
|
||||
|
||||
@Override
|
||||
public List<BoaAppType> getUserApps(BoaUser user) {
|
||||
if (user == null || user.getId() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// PC 浏览器端;UserBase 侧已按 userId 权限过滤(组开通 ∪ 角色模块所属应用,超管全量)
|
||||
return YschBaseOpenApi.getUserApp(user.getId(), ClientEnum.PC_BROWSER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BoaApp> getAppById(BoaUser user, Integer appId) {
|
||||
if (appId == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return getUserApps(user).stream()
|
||||
.filter(t -> t.getApps() != null)
|
||||
.flatMap(t -> t.getApps().stream())
|
||||
.filter(a -> appId.equals(a.getId()))
|
||||
.findFirst();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.yunhai.userhome.service.impl;
|
||||
|
||||
import com.yunhai.platform.utils.model.BoaApp;
|
||||
import com.yunhai.platform.utils.model.BoaAppType;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import com.yunhai.userhome.entity.UsedApp;
|
||||
import com.yunhai.userhome.model.SetType;
|
||||
import com.yunhai.userhome.repository.UsedAppRepository;
|
||||
import com.yunhai.userhome.service.AppRemoteService;
|
||||
import com.yunhai.userhome.service.UsedAppService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class UsedAppServiceImpl implements UsedAppService {
|
||||
|
||||
@Autowired
|
||||
private UsedAppRepository usedAppRepository;
|
||||
|
||||
@Autowired
|
||||
private AppRemoteService appRemoteService;
|
||||
|
||||
@Override
|
||||
public void save(UsedApp usedApp) {
|
||||
Optional<UsedApp> model = usedAppRepository
|
||||
.findFirstBySetIdAndTypeAndRoleTypeAndSchId(usedApp.getSetId(), usedApp.getType(),
|
||||
usedApp.getRoleType(), usedApp.getSchId());
|
||||
if (model.isPresent()) {
|
||||
usedApp.setId(model.get().getId());
|
||||
}
|
||||
usedAppRepository.save(usedApp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UsedApp> findById(Integer schId, Integer uid, Integer roleType) {
|
||||
List<UsedApp> list = usedAppRepository.findAll(select(schId, uid, roleType));
|
||||
Optional<UsedApp> baseMod = list.stream()
|
||||
.filter(x -> x.getType() == SetType.BASE)
|
||||
.sorted(Comparator.comparing(UsedApp::getCDate).reversed())
|
||||
.findFirst();
|
||||
Optional<UsedApp> schMod = list.stream()
|
||||
.filter(x -> x.getType() == SetType.SCHOOL)
|
||||
.sorted(Comparator.comparing(UsedApp::getCDate).reversed())
|
||||
.findFirst();
|
||||
Optional<UsedApp> userMod = list.stream()
|
||||
.filter(x -> x.getType() == SetType.USER)
|
||||
.sorted(Comparator.comparing(UsedApp::getCDate).reversed())
|
||||
.findFirst();
|
||||
if (schId != null && schId.equals(uid)) {
|
||||
return schMod;
|
||||
}
|
||||
// 优先级:用户 > 学校 > 系统
|
||||
if (userMod.isPresent()) {
|
||||
return userMod;
|
||||
}
|
||||
if (schMod.isPresent()) {
|
||||
return schMod;
|
||||
}
|
||||
return baseMod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BoaApp> getUsedAppList(Integer schId, Integer uid, Integer roleType, BoaUser user) {
|
||||
List<String> appIdList = new ArrayList<>();
|
||||
Optional<UsedApp> data = findById(schId, uid, roleType);
|
||||
if (data.isPresent() && data.get().getAppIds() != null) {
|
||||
String usedStr = data.get().getAppIds();
|
||||
if (!usedStr.trim().isEmpty()) {
|
||||
appIdList = Arrays.asList(usedStr.split(","));
|
||||
}
|
||||
}
|
||||
if (appIdList.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<BoaApp> appList = flattenApps(appRemoteService.getUserApps(user));
|
||||
Map<Integer, BoaApp> appMap = appList.stream()
|
||||
.collect(Collectors.toMap(BoaApp::getId, a -> a, (a, b) -> a));
|
||||
List<BoaApp> result = new ArrayList<>();
|
||||
for (String appId : appIdList) {
|
||||
try {
|
||||
BoaApp app = appMap.get(Integer.parseInt(appId.trim()));
|
||||
if (app != null) {
|
||||
result.add(app);
|
||||
}
|
||||
} catch (NumberFormatException ignore) {
|
||||
// 脏数据容错
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveUserId(UsedApp usedApp) {
|
||||
Optional<UsedApp> model = usedAppRepository
|
||||
.findFirstBySetIdAndTypeAndRoleType(usedApp.getSetId(), SetType.USER, -1);
|
||||
if (model.isPresent()) {
|
||||
usedApp.setId(model.get().getId());
|
||||
}
|
||||
usedAppRepository.save(usedApp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UsedApp> findByUserId(Integer uid) {
|
||||
return usedAppRepository.findFirstBySetIdAndTypeAndRoleType(uid, SetType.USER, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getUsedAppMapList(BoaUser user, Integer uid) {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
Optional<UsedApp> data = findByUserId(uid);
|
||||
if (!data.isPresent() || data.get().getAppIds() == null) {
|
||||
return list;
|
||||
}
|
||||
List<String> appIds = Arrays.asList(data.get().getAppIds().split(","));
|
||||
List<BoaApp> appList = flattenApps(appRemoteService.getUserApps(user));
|
||||
Map<Integer, BoaApp> appMap = appList.stream()
|
||||
.collect(Collectors.toMap(BoaApp::getId, a -> a, (a, b) -> a));
|
||||
for (String appId : appIds) {
|
||||
try {
|
||||
BoaApp app = appMap.get(Integer.parseInt(appId.trim()));
|
||||
if (app != null) {
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("id", app.getId());
|
||||
m.put("name", app.getName());
|
||||
m.put("icon", app.getIcon());
|
||||
m.put("url", app.getWebAddr());
|
||||
list.add(m);
|
||||
}
|
||||
} catch (NumberFormatException ignore) {
|
||||
// 脏数据容错
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/** BoaAppType 分组平铺为 BoaApp 列表。 */
|
||||
private List<BoaApp> flattenApps(List<BoaAppType> types) {
|
||||
List<BoaApp> apps = new ArrayList<>();
|
||||
if (types == null) {
|
||||
return apps;
|
||||
}
|
||||
for (BoaAppType type : types) {
|
||||
if (type.getApps() != null) {
|
||||
apps.addAll(type.getApps());
|
||||
}
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
/** 一级常用生效范围:BASE(按角色) OR SCHOOL(setId=schId+角色) OR USER(setId=uid+角色+schId)。 */
|
||||
private Specification<UsedApp> select(Integer schId, Integer uid, Integer roleType) {
|
||||
return (Root<UsedApp> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
|
||||
Predicate basePre = cb.and(
|
||||
cb.equal(root.get("type"), SetType.BASE),
|
||||
cb.equal(root.get("roleType"), roleType));
|
||||
Predicate schPer = cb.and(
|
||||
cb.equal(root.get("setId"), schId),
|
||||
cb.equal(root.get("type"), SetType.SCHOOL),
|
||||
cb.equal(root.get("roleType"), roleType));
|
||||
Predicate userPer = cb.and(
|
||||
cb.equal(root.get("setId"), uid),
|
||||
cb.equal(root.get("type"), SetType.USER),
|
||||
cb.equal(root.get("roleType"), roleType),
|
||||
cb.equal(root.get("schId"), schId));
|
||||
return cb.or(basePre, schPer, userPer);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.yunhai.userhome.service.impl;
|
||||
|
||||
import com.yunhai.userhome.entity.UserCurrentRole;
|
||||
import com.yunhai.userhome.repository.UserCurrentRoleRepository;
|
||||
import com.yunhai.userhome.service.IUserCurrentRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class UserCurrentRoleServiceImpl implements IUserCurrentRoleService {
|
||||
|
||||
@Autowired
|
||||
private UserCurrentRoleRepository repository;
|
||||
|
||||
@Override
|
||||
public Optional<UserCurrentRole> findById(Integer userId) {
|
||||
return repository.findByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(UserCurrentRole role) {
|
||||
repository.save(role);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user