build / build-push (push) Successful in 1m36s
- SvcHallClient:由手搓 IDHttp + yh.svchall.base-url 拼 URL 改为 YschOpenCall 命名目标 svchall(服务目录 yh.open.services.svchall)。原形态对带 context-path 的 svc-hall 必 401(共享拦截器只剥 yh.open.base-path=/userbase);per-target base-path 与提供方 ctx 对齐后签名天然一致。目录未配时回落 legacy 键;两者皆缺则构造期 fail-fast。 - SvcItemRemoteQuery:新增 businessAbsent 判定,统一两条出站路径的「业务 code=2 → 404 哨兵/空集,其余上抛」语义(目录路径抛 DException,legacy 抛 DHttpException)。 - import 迁移:YschBaseOpenApi → openapi.base.*(SDK 领域分包)。 - application.yml:新增 yh.open.services.svchall,删 yh.svchall.base-url。 - 测试:新增 SvcHallClientTest(8 例:目录目标/参数映射/空参不下发/fire-and-forget/ 回落/fail-fast);SvcItemRemoteQueryTest 补目录路径错误语义 4 例。104 测试全绿。
120 lines
4.8 KiB
Java
120 lines
4.8 KiB
Java
package com.yunhai.cms.service.impl;
|
|
|
|
import com.yunhai.cms.model.vo.SchoolVo;
|
|
import com.yunhai.cms.model.vo.SiteVo;
|
|
import com.yunhai.cms.repository.CmsArticleRepository;
|
|
import com.yunhai.platform.apistd.BizException;
|
|
import com.yunhai.platform.openapi.base.YschBaseOpenApi;
|
|
import com.yunhai.platform.utils.exception.ErrorCode;
|
|
import com.yunhai.platform.utils.model.BoaGroup;
|
|
import com.yunhai.platform.utils.model.BoaUser;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 学校工作台(docs/09 §3.3,方案A 双层壳):
|
|
* ① listFor —— 学校卡片 = 顶层站点(主站),院系子站经 parentSiteId 归属;
|
|
* 权限语义与 {@link SiteService#listFor} 完全一致(超管全部 / 校级本校 / 无角色空)。
|
|
* ② schoolOptions —— 「添加学校」选择器:代理 UserBase oapi getGroupTree 过滤 type=2(学校组),
|
|
* 只绑定不跨系统写(D6-4);平台不可达降级空数组(CmsUserCenterService 同款)。
|
|
*/
|
|
@Slf4j
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
public class SchoolService {
|
|
|
|
/** UserBase GroupTypeEnum.SCHOOL_GROUP:学校组节点类型 */
|
|
private static final int GROUP_TYPE_SCHOOL = 2;
|
|
|
|
private final SiteService siteService;
|
|
private final CmsArticleRepository articleRepository;
|
|
|
|
/** 学校工作台列表:当前用户可见的顶层站点逐站聚合成学校卡片 */
|
|
public List<SchoolVo> listFor(BoaUser user) {
|
|
List<SiteVo> sites = siteService.listFor(user);
|
|
List<SchoolVo> result = new ArrayList<>();
|
|
for (SiteVo top : sites) {
|
|
if (top.getParentSiteId() != null && top.getParentSiteId() > 0) {
|
|
continue;
|
|
}
|
|
SchoolVo vo = new SchoolVo();
|
|
vo.setSchId(top.getSchId());
|
|
vo.setSchName(top.getSchName());
|
|
vo.setMainSiteId(top.getId());
|
|
vo.setMainSiteCode(top.getCode());
|
|
vo.setMainSitePath(top.getPath());
|
|
vo.setMainSiteName(top.getName());
|
|
vo.setTheme(top.getTheme());
|
|
vo.setStatus(top.getStatus());
|
|
// 院系子站按 parentSiteId 归属(同权限范围内统计)
|
|
long articleCount = 0;
|
|
int siteCount = 1;
|
|
for (SiteVo s : sites) {
|
|
if (s.getParentSiteId() != null && top.getId().equals(s.getParentSiteId())) {
|
|
siteCount++;
|
|
}
|
|
}
|
|
for (SiteVo s : sites) {
|
|
boolean own = s.getId().equals(top.getId());
|
|
boolean child = s.getParentSiteId() != null && top.getId().equals(s.getParentSiteId());
|
|
if (own || child) {
|
|
articleCount += articleRepository.countBySiteId(s.getId());
|
|
}
|
|
}
|
|
vo.setSiteCount(siteCount);
|
|
vo.setArticleCount(articleCount);
|
|
result.add(vo);
|
|
}
|
|
result.sort((a, b) -> Integer.compare(a.getMainSiteId(), b.getMainSiteId()));
|
|
return result;
|
|
}
|
|
|
|
/** UserBase 学校选项(仅超管;添加学校=绑定已有学校,不新建) */
|
|
public List<SchoolVo.Option> schoolOptions(BoaUser user) {
|
|
siteService.requireSuperAdmin(user);
|
|
BoaGroup root;
|
|
try {
|
|
root = YschBaseOpenApi.getGroupTree();
|
|
} catch (Exception e) {
|
|
log.warn("[cms] 获取 UserBase 学校组树失败,学校选项降级为空: {}", e.getMessage());
|
|
return Collections.emptyList();
|
|
}
|
|
List<SchoolVo.Option> options = new ArrayList<>();
|
|
collectSchools(root, options);
|
|
return options;
|
|
}
|
|
|
|
private void collectSchools(BoaGroup node, List<SchoolVo.Option> out) {
|
|
if (node == null) {
|
|
return;
|
|
}
|
|
if (node.getType() != null && node.getType() == GROUP_TYPE_SCHOOL) {
|
|
out.add(new SchoolVo.Option(node.getId(), node.getName()));
|
|
}
|
|
if (node.getChildren() != null) {
|
|
for (BoaGroup child : node.getChildren()) {
|
|
collectSchools(child, out);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** 工作台卡片挂载的站点摘要(供校名下拉/快速切换;权限复用 listFor) */
|
|
public Map<Integer, List<SiteVo>> sitesGroupedByMain(BoaUser user) {
|
|
List<SiteVo> sites = siteService.listFor(user);
|
|
Map<Integer, List<SiteVo>> grouped = new LinkedHashMap<>();
|
|
for (SiteVo s : sites) {
|
|
Integer mainId = (s.getParentSiteId() == null || s.getParentSiteId() <= 0)
|
|
? s.getId() : s.getParentSiteId();
|
|
grouped.computeIfAbsent(mainId, k -> new ArrayList<>()).add(s);
|
|
}
|
|
return grouped;
|
|
}
|
|
}
|