项目初始化提交,移除仓库默认README
build / build-push (push) Failing after 48s

This commit is contained in:
chenxing
2026-08-21 09:37:21 +08:00
parent 729e1d0c35
commit 000993df80
30 changed files with 1497 additions and 0 deletions
@@ -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);
}
}