Files
YschcmsService/src/main/java/com/yunhai/cms/service/impl/SchoolService.java
T
chenxing 649ad66264
build / build-push (push) Successful in 1m36s
refactor(sdk)!: CMS→svc-hall 出站改走 YschOpenCall 命名目标 + 适配 SDK 领域分包
- 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 测试全绿。
2026-09-16 21:05:55 +08:00

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;
}
}