feat(admin): 新增小组激活状态清单接口 /api/admin/teams

- router:GET /api/admin/teams(adminAuth;固定路径段,与既有路由无通配冲突)

- controller:teams() 整体透传 group/activated/includeTest(防前端筛选静默失效)

- service:getTeams(),键 = 组别+队伍号;成员并集 aggregation.team_uid ∪ contestants.team_id;学校取 aggregation.organization_cn;激活 = 全组成员均已激活;附 summary 与 schoolConflict

- model/aggregation:补声明运行库既有列 organization_cn / group(此前模型漏声明 ⇒ 查询被当未知列)

线上验证:R86 已部署上线,公网 /api/admin/teams 返回 401(鉴权在位)
This commit is contained in:
2026-10-09 09:33:05 +08:00
parent 481de69e3d
commit c101b15e2e
4 changed files with 221 additions and 0 deletions

View File

@@ -126,6 +126,30 @@ class AdminController extends Controller {
}
}
/**
* 获取「小组(团队)激活状态」清单(R84 续六新增)
* GET /api/admin/teams?group=xxx&activated=true|false&includeTest=0|1
*
* 需求:「选手管理」中查看已激活/未激活小组,**必须携带小组所属学校名称**。
* 口径(键 = 组别 + 队伍号;成员 = aggregation.team_uid ∪ contestants.team_id;
* 学校 = aggregation.organization_cn;激活 = 全组成员均已激活)详见
* `service/admin.js#getTeams` 的方法头注释 —— 那是唯一真相源。
*/
async teams() {
const { ctx, service } = this;
if (!this._ensureAdmin()) return;
try {
// ⚠️ 筛选条件必须**整体透传**(同 accounts():曾因只解构部分参数导致前端筛选静默失效)
const { group, activated, includeTest } = ctx.query;
const result = await service.admin.getTeams({ group, activated, includeTest });
ctx.body = ctx.helper.success(result, '获取小组列表成功');
} catch (err) {
ctx.logger.error('获取小组列表失败:', err);
ctx.body = ctx.helper.error(500, '获取小组列表失败');
}
}
/**
* 从 Excel 文件导入账号数据
* POST /api/admin/import-excel