- 角色字典实测校准(采样 200+ 账号 currentRole/roles): 1 老师 / 2 校领导 / 3 学生 / 4 家长 / 5 局领导 / 6 工作号 / 7 管理员 → agent.roles: student=[3] teacher=[1,6] parent=[4] admin=[2,5,7] (旧默认 student=[1]/teacher=[2,3]/admin=[4..7] 系臆测,导致老师账号被显示为学生) - 新增家长身份 AgentRole.PARENT;活动报名/取消改由 STUDENT_OR_PARENT 放行 - 当前身份识别增加 roleName 关键词兜底,避免识别不出就降级为访客 - 移除资源库对接:删除 ResourceTools 及注册/编排/agent.modules/module-landing - 测试 48/48 通过
This commit is contained in:
@@ -3,18 +3,27 @@ package com.yunhai.agent.auth;
|
||||
/**
|
||||
* 智能体侧的角色分类(由平台 {@code BoaUser} 解析而来)。
|
||||
*
|
||||
* <p>用途:决定「这个身份能用哪些工具」——学生侧(请假申请 / 交作业 / 报名活动 / 看公告)
|
||||
* 与教职工侧(发公告 / 审批请假 / 发布资源 / 专业发展)严格分开。
|
||||
* <p>用途:决定「这个身份能用哪些工具」——学生侧(请假申请 / 交作业 / 报名活动 / 看公告)、
|
||||
* 家长侧(报名活动 / 宿舍通知回执)与教职工侧(发公告 / 审批请假 / 专业发展)严格分开。
|
||||
*
|
||||
* <p>对齐平台 UserBase 的「用户身份」字典(门户/GetUserInfo 的 {@code currentRole.roleId}):
|
||||
* <pre>
|
||||
* 1 老师 2 校领导 3 学生 4 家长 5 局领导 6 工作号 7 管理员
|
||||
* </pre>
|
||||
* 映射到本枚举:1/6 → 教师,3 → 学生,4 → 家长,2/5/7 → 管理员。
|
||||
*/
|
||||
public enum AgentRole {
|
||||
|
||||
/** 学生 */
|
||||
STUDENT("学生"),
|
||||
|
||||
/** 教师(含班主任) */
|
||||
/** 教师(含班主任、工作号/教职工) */
|
||||
TEACHER("教师"),
|
||||
|
||||
/** 管理员(校管 / 分管领导 / 教务 / 校长) */
|
||||
/** 家长:家校活动的报名方、宿舍通知的回执方 */
|
||||
PARENT("家长"),
|
||||
|
||||
/** 管理员(校领导 / 局领导 / 管理员) */
|
||||
ADMIN("管理员"),
|
||||
|
||||
/** 访客:未登录或无法识别角色,只能使用公共只读能力 */
|
||||
|
||||
@@ -14,13 +14,14 @@ import java.util.Set;
|
||||
* 集中成一张可读的表比散落在 7 个模块的工具定义里更容易审阅与改动;
|
||||
* 若某个工具需要就近声明,用 {@code ToolDef.allow(...)} 显式指定即可(本策略会尊重已有声明)。
|
||||
*
|
||||
* <p>三类名单:
|
||||
* <p>名单:
|
||||
* <ul>
|
||||
* <li>{@link #STAFF_ONLY} —— 教职工侧(教师 + 管理员):审批、发布、统计、宿管、专业发展;</li>
|
||||
* <li>{@link #STUDENT_ONLY} —— 学生侧:交作业、报名活动、销假;</li>
|
||||
* <li>{@link #STUDENT_ONLY} —— 学生侧:交作业、销假;</li>
|
||||
* <li>{@link #STUDENT_OR_PARENT} —— 家校活动报名:家长与学生都可发起;</li>
|
||||
* <li>{@link #SHARED} —— 学生与教职工都可能发起的:请假申请/撤销。</li>
|
||||
* </ul>
|
||||
* 未列入任何名单的工具 = 所有已识别角色都可用(如各类只读查询)。
|
||||
* 未列入任何名单的工具 = 所有已识别角色都可用(如各类只读查询、宿舍通知回执)。
|
||||
*/
|
||||
public final class RolePolicy {
|
||||
|
||||
@@ -43,10 +44,14 @@ public final class RolePolicy {
|
||||
/** 学生专属 */
|
||||
private static final Set<String> STUDENT_ONLY = new HashSet<>(Arrays.asList(
|
||||
"homework.myList", "homework.detail", "homework.result", "homework.submit",
|
||||
"activity.signup", "activity.cancelSignup",
|
||||
"leave.reportBack"
|
||||
));
|
||||
|
||||
/** 学生与家长共用(家校活动报名由家长或学生发起) */
|
||||
private static final Set<String> STUDENT_OR_PARENT = new HashSet<>(Arrays.asList(
|
||||
"activity.signup", "activity.cancelSignup"
|
||||
));
|
||||
|
||||
/** 学生与教职工共用(发起/撤销自己的事项) */
|
||||
private static final Set<String> SHARED = new HashSet<>(Arrays.asList(
|
||||
"leave.submit", "leave.withdraw"
|
||||
@@ -71,6 +76,8 @@ public final class RolePolicy {
|
||||
d.allow(AgentRole.TEACHER, AgentRole.ADMIN);
|
||||
} else if (STUDENT_ONLY.contains(n)) {
|
||||
d.allow(AgentRole.STUDENT);
|
||||
} else if (STUDENT_OR_PARENT.contains(n)) {
|
||||
d.allow(AgentRole.STUDENT, AgentRole.PARENT);
|
||||
} else if (SHARED.contains(n)) {
|
||||
d.allow(AgentRole.STUDENT, AgentRole.TEACHER, AgentRole.ADMIN);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.yunhai.agent.config.AgentSettings;
|
||||
import com.yunhai.platform.utils.model.BoaRoleInfo;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -19,17 +20,28 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* 平台里一个账号可以同时挂多个身份:{@code BoaUser.roleIds} 是<b>全部</b>身份的角色号,
|
||||
* {@code BoaUser.currentRole} 是用户在门户里<b>当前激活</b>的那个身份
|
||||
* (等价于 {@code YschBaseOpenApi.getCurrentIdentity(userId)})。
|
||||
* 例如实测账号 10008 同时是「学生 + 管理员 + 教师」——若把所有身份并集,
|
||||
* 权限只增不减、能力边界完全模糊(所有人都是全量 54 项)。
|
||||
* 因此这里<b>只认当前身份</b>:与学校门户、其它业务模块的口径保持一致。
|
||||
* 实测账号 10008(李晶/lijing)挂着「老师(1)」与「管理员(7)」,门户当前身份是「老师」——
|
||||
* 若把所有身份并集,权限只增不减、能力边界完全模糊。
|
||||
* 因此这里<b>只认当前身份</b>:与学校门户、其它业务模块的口径保持一致(2026-10-10 改)。
|
||||
*
|
||||
* <h3>判定规则(角色号可在 {@code agent.roles.*} 配置)</h3>
|
||||
* <h3>★ 角色号实测校准(2026-10-12,采样 200+ 账号的 currentRole / roles 取得)</h3>
|
||||
* <pre>
|
||||
* 1 老师 2 校领导 3 学生 4 家长 5 局领导 6 工作号 7 管理员
|
||||
* → 本枚举:1/6 = 教师,3 = 学生,4 = 家长,2/5/7 = 管理员
|
||||
* </pre>
|
||||
* 数据源与门户顶栏、{@code /notice/api/base/GetUserInfo} 一致(都是 {@code BoaUser.currentRole})。
|
||||
* 本工程此前的默认映射(student=1 / teacher=2,3 / admin=4..7)是<b>猜的</b>,
|
||||
* 把 roleId=1 误当学生 —— 于是「李晶(老师)」在助手里显示成「学生」。
|
||||
* 现已按 {@code agent.roles.*} 配置修正(默认值见 {@link AgentSettings.Roles})。
|
||||
*
|
||||
* <h3>判定顺序</h3>
|
||||
* <ol>
|
||||
* <li>优先取 {@code currentRole.getRoleId()},命中 {@code agent.roles.student/teacher/admin}
|
||||
* 即获得对应角色,且<b>只</b>获得这一个身份;</li>
|
||||
* <li>当前身份是管理员时,按 {@code agent.roles.admin-also-teacher=true} 追加教师能力;</li>
|
||||
* <li>当前身份号未在配置里声明(或账号没有当前身份)→ 回退按 {@code roleIds}/{@code type}
|
||||
* 的旧口径判定,并打 WARN 日志提示补配置;</li>
|
||||
* <li><b>当前身份</b>:先按 {@code roleId} 命中 {@code agent.roles.*};
|
||||
* 角色号没配到,再按 {@code roleName} 关键词兜底(老师/教师/班主任 → 教师,
|
||||
* 管理员/校长/主任/教务… → 管理员,家长 → 家长,学生 → 学生);命中即<b>只</b>返回该身份;</li>
|
||||
* <li>当前身份是管理员时,按 {@code admin-also-teacher=true} 追加教师能力;</li>
|
||||
* <li>无当前身份(或当前身份识别不出)→ 回退按 {@code roleIds} 逐个匹配配置;</li>
|
||||
* <li>仍然什么都没识别出 → 按 {@code BoaUser.type} 兜底(0=学生、2=教职工、1=超管);</li>
|
||||
* <li>什么都识别不出 → 访客(仅公共只读能力)。</li>
|
||||
* </ol>
|
||||
*/
|
||||
@@ -37,6 +49,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@Component
|
||||
public class RoleResolver {
|
||||
|
||||
/** 角色名关键词:命中即判定(角色号未配置时的兜底,跨学校更稳) */
|
||||
private static final String[] ADMIN_WORDS = {
|
||||
"管理", "校长", "园长", "局长", "领导", "主任", "教务", "督导", "书记", "党委"
|
||||
};
|
||||
private static final String[] TEACHER_WORDS = {"教师", "老师", "班主任", "教工"};
|
||||
|
||||
private final AgentSettings settings;
|
||||
|
||||
/** 每个用户上次记录过的身份描述,避免每请求刷屏(只在身份变化时打一次 INFO) */
|
||||
@@ -58,20 +76,21 @@ public class RoleResolver {
|
||||
|
||||
// 1) ★ 平台「当前身份」优先 —— 一个账号只生效一个身份
|
||||
BoaRoleInfo current = user.getCurrentRole();
|
||||
if (current != null && current.getRoleId() != null) {
|
||||
Set<AgentRole> hit = match(current.getRoleId(), cfg);
|
||||
if (current != null && (current.getRoleId() != null || StringUtils.isNotBlank(current.getRoleName()))) {
|
||||
Set<AgentRole> hit = matchCurrent(current, cfg);
|
||||
if (!hit.isEmpty()) {
|
||||
applyAdminAlsoTeacher(hit, cfg);
|
||||
logResolved(user, current, hit, "当前身份");
|
||||
return hit;
|
||||
}
|
||||
log.warn("[身份] 当前身份 roleId={} roleName={} 未命中 agent.roles.* 配置,"
|
||||
+ "暂按账号全部身份兜底(userId={}, roleIds={})—— 建议把该角色号补进配置",
|
||||
log.warn("[身份] 当前身份 roleId={} roleName={} 既未命中 agent.roles.* 配置、"
|
||||
+ "角色名也不含可识别关键词,暂按账号全部身份兜底(userId={}, roleIds={})"
|
||||
+ "—— 建议把该角色号补进配置",
|
||||
current.getRoleId(), current.getRoleName(), user.getId(), user.getRoleIds());
|
||||
}
|
||||
|
||||
// 2) 兜底:没有当前身份,或当前身份号未配置
|
||||
if (user.getType() != null && user.getType() == 1) {
|
||||
// 2) 兜底:账号全部角色号 + 超管口径
|
||||
if (user.getType() != null && cfg.getAdminUserTypes().contains(user.getType())) {
|
||||
roles.add(AgentRole.ADMIN);
|
||||
}
|
||||
List<Integer> roleIds = user.getRoleIds();
|
||||
@@ -82,13 +101,18 @@ public class RoleResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
applyAdminAlsoTeacher(roles, cfg);
|
||||
|
||||
// 3) 仍未识别出任何角色 → 按 BoaUser.type 兜底(学生没有角色号,只能靠这一条)
|
||||
if (roles.isEmpty()) {
|
||||
roles.addAll(matchByUserType(user.getType(), cfg));
|
||||
}
|
||||
|
||||
applyAdminAlsoTeacher(roles, cfg);
|
||||
if (roles.isEmpty()) {
|
||||
roles.add(AgentRole.GUEST);
|
||||
}
|
||||
logResolved(user, current, roles,
|
||||
current == null ? "无当前身份,按账号全部身份" : "当前身份未配置,按账号全部身份");
|
||||
current == null ? "无当前身份,按账号全部身份" : "当前身份未识别,按账号全部身份");
|
||||
return roles;
|
||||
}
|
||||
|
||||
@@ -107,6 +131,15 @@ public class RoleResolver {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** 当前身份 → 智能体角色:角色号配置优先,角色名关键词兜底 */
|
||||
private Set<AgentRole> matchCurrent(BoaRoleInfo current, AgentSettings.Roles cfg) {
|
||||
Set<AgentRole> hit = match(current.getRoleId(), cfg);
|
||||
if (hit.isEmpty() && StringUtils.isNotBlank(current.getRoleName())) {
|
||||
hit = matchByRoleName(current.getRoleName().trim());
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
/** 单个角色号 → 智能体角色(一个号理论上可命中多个分组,全部保留) */
|
||||
private Set<AgentRole> match(Integer roleId, AgentSettings.Roles cfg) {
|
||||
Set<AgentRole> hit = new LinkedHashSet<>();
|
||||
@@ -122,6 +155,51 @@ public class RoleResolver {
|
||||
if (contains(cfg.getStudent(), roleId)) {
|
||||
hit.add(AgentRole.STUDENT);
|
||||
}
|
||||
if (contains(cfg.getParent(), roleId)) {
|
||||
hit.add(AgentRole.PARENT);
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
/** 角色名 → 智能体角色(角色号没配到时的兜底,避免「未识别 → 访客」) */
|
||||
private Set<AgentRole> matchByRoleName(String name) {
|
||||
Set<AgentRole> hit = new LinkedHashSet<>();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
return hit;
|
||||
}
|
||||
if (containsAny(name, ADMIN_WORDS)) {
|
||||
hit.add(AgentRole.ADMIN);
|
||||
}
|
||||
if (containsAny(name, TEACHER_WORDS)) {
|
||||
hit.add(AgentRole.TEACHER);
|
||||
}
|
||||
if (name.contains("学生")) {
|
||||
hit.add(AgentRole.STUDENT);
|
||||
}
|
||||
if (name.contains("家长")) {
|
||||
hit.add(AgentRole.PARENT);
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
/** {@code BoaUser.type} → 智能体角色(学生没有角色号,这是学生的唯一入口) */
|
||||
private Set<AgentRole> matchByUserType(Integer type, AgentSettings.Roles cfg) {
|
||||
Set<AgentRole> hit = new LinkedHashSet<>();
|
||||
if (type == null) {
|
||||
return hit;
|
||||
}
|
||||
if (contains(cfg.getStudentUserTypes(), type)) {
|
||||
hit.add(AgentRole.STUDENT);
|
||||
}
|
||||
if (contains(cfg.getTeacherUserTypes(), type)) {
|
||||
hit.add(AgentRole.TEACHER);
|
||||
}
|
||||
if (contains(cfg.getAdminUserTypes(), type)) {
|
||||
hit.add(AgentRole.ADMIN);
|
||||
}
|
||||
if (contains(cfg.getParentUserTypes(), type)) {
|
||||
hit.add(AgentRole.PARENT);
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
@@ -148,6 +226,15 @@ public class RoleResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsAny(String name, String[] words) {
|
||||
for (String w : words) {
|
||||
if (name.contains(w)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean contains(List<Integer> list, int v) {
|
||||
return list != null && list.contains(v);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ public class AgentSettings {
|
||||
* dormnotice → /par/notices 宿舍通知箱
|
||||
* familyactivity → /par/activities 活动广场
|
||||
* coursehomework → /stu/today 今日作业
|
||||
* resourcelibrary → /resource 资源管理
|
||||
* profession → /home 发展首页
|
||||
* </pre>
|
||||
* 运维可在 {@code application.yml} 用 {@code agent.module-landing.<模块>=<路由>} 覆盖单个模块;
|
||||
@@ -67,7 +66,6 @@ public class AgentSettings {
|
||||
m.put("dormnotice", "/par/notices");
|
||||
m.put("familyactivity", "/par/activities");
|
||||
m.put("coursehomework", "/stu/today");
|
||||
m.put("resourcelibrary", "/resource");
|
||||
m.put("profession", "/home");
|
||||
return m;
|
||||
}
|
||||
@@ -173,16 +171,34 @@ public class AgentSettings {
|
||||
*/
|
||||
@Data
|
||||
public static class Roles {
|
||||
/** 学生角色号(默认 1;请按 UserBase 校准) */
|
||||
private List<Integer> student = new ArrayList<>(Arrays.asList(1));
|
||||
/** 学生角色号。★ 实测校准(2026-10-12):{@code 3 = 学生} */
|
||||
private List<Integer> student = new ArrayList<>(Arrays.asList(3));
|
||||
|
||||
/** 教师角色号(默认 2=教师、3=班主任;请按 UserBase 校准) */
|
||||
private List<Integer> teacher = new ArrayList<>(Arrays.asList(2, 3));
|
||||
/** 教师角色号。★ 实测校准:{@code 1 = 老师}、{@code 6 = 工作号}(教职工工号身份) */
|
||||
private List<Integer> teacher = new ArrayList<>(Arrays.asList(1, 6));
|
||||
|
||||
/** 管理员角色号(默认 4=校管、5=分管领导、6=教务、7=校长;请按 UserBase 校准) */
|
||||
private List<Integer> admin = new ArrayList<>(Arrays.asList(4, 5, 6, 7));
|
||||
/** 家长角色号。★ 实测校准:{@code 4 = 家长} */
|
||||
private List<Integer> parent = new ArrayList<>(Arrays.asList(4));
|
||||
|
||||
/** 管理员是否天然拥有教师能力(默认 true:校管/领导可用教师侧工具) */
|
||||
/** 管理员角色号。★ 实测校准:{@code 2 = 校领导}、{@code 5 = 局领导}、{@code 7 = 管理员} */
|
||||
private List<Integer> admin = new ArrayList<>(Arrays.asList(2, 5, 7));
|
||||
|
||||
/**
|
||||
* 兜底口径之一:账号既没有「当前身份」、也没挂任何已识别的角色号时,
|
||||
* 按 {@code BoaUser.type} 判定。实测 {@code 0 = 学生}。
|
||||
*/
|
||||
private List<Integer> studentUserTypes = new ArrayList<>(Arrays.asList(0));
|
||||
|
||||
/** 兜底口径之二:{@code 2 = 教职工} */
|
||||
private List<Integer> teacherUserTypes = new ArrayList<>(Arrays.asList(2));
|
||||
|
||||
/** 兜底口径之三:{@code 1 = 平台超管} */
|
||||
private List<Integer> adminUserTypes = new ArrayList<>(Arrays.asList(1));
|
||||
|
||||
/** 兜底口径之四:家长(平台暂未见稳定的 {@code type} 口径,留空待校准) */
|
||||
private List<Integer> parentUserTypes = new ArrayList<>();
|
||||
|
||||
/** 管理员是否天然拥有教师能力(默认 true:校领导/局领导/管理员可用教师侧工具) */
|
||||
private boolean adminAlsoTeacher = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -940,7 +940,6 @@ public class AgentOrchestrator {
|
||||
case "dormnotice": return "宿舍通知";
|
||||
case "familyactivity": return "家校活动";
|
||||
case "coursehomework": return "课程作业";
|
||||
case "resourcelibrary": return "资源库";
|
||||
case "profession": return "教师专业发展";
|
||||
default: return module;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.yunhai.agent.tool.defs.DormNoticeTools;
|
||||
import com.yunhai.agent.tool.defs.HomeworkTools;
|
||||
import com.yunhai.agent.tool.defs.LeaveTools;
|
||||
import com.yunhai.agent.tool.defs.ProfessionTools;
|
||||
import com.yunhai.agent.tool.defs.ResourceTools;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -75,7 +74,6 @@ public class ToolRegistry {
|
||||
register(DormNoticeTools.defs());
|
||||
register(ActivityTools.defs());
|
||||
register(HomeworkTools.defs());
|
||||
register(ResourceTools.defs());
|
||||
register(ProfessionTools.defs());
|
||||
// 套用「学生 / 教师」角色能力策略(未显式声明角色的工具在此落定)
|
||||
RolePolicy.apply(tools.values());
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.yunhai.agent.tool.defs;
|
||||
|
||||
import com.yunhai.agent.tool.ToolDef;
|
||||
import com.yunhai.agent.tool.ToolParam;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源库模块工具 —— 后端 ResourceLibrary,前缀 /api/resource、/api/category、/api/textbook。
|
||||
*/
|
||||
public final class ResourceTools {
|
||||
|
||||
public static final String MODULE = "resourcelibrary";
|
||||
|
||||
private ResourceTools() {
|
||||
}
|
||||
|
||||
public static List<ToolDef> defs() {
|
||||
List<ToolDef> list = new ArrayList<>();
|
||||
|
||||
list.add(ToolDef.of("resource.search", MODULE, "检索资源",
|
||||
"按关键词/分类/学科检索教学资源(课件、教案、试题等)。用户问“找一份 XX 的课件”“有没有 XX 资料”时用它。",
|
||||
"GET", "/api/resource/List")
|
||||
.p(ToolParam.optional("keyword", "string", "关键词:资源名称 / 编码 / 上传人"),
|
||||
ToolParam.optional("categoryId", "integer", "分类节点 id(含子节点)"),
|
||||
ToolParam.optional("subject", "string", "学科"),
|
||||
ToolParam.optional("type", "string", "资源类型"),
|
||||
ToolParam.optional("orderBy", "string", "排序:time_desc 最新 / download_desc 下载最多 / view_desc 浏览最多"),
|
||||
ToolParam.optional("pageIndex", "integer", "页码").dft("1"),
|
||||
ToolParam.optional("pageSize", "integer", "每页条数").dft("10"))
|
||||
.readAt("/resource"));
|
||||
|
||||
list.add(ToolDef.of("resource.detail", MODULE, "资源详情",
|
||||
"查看一份资源的详细信息(分类、学科、格式、下载量等)。",
|
||||
"GET", "/api/resource/Detail")
|
||||
.p(ToolParam.required("id", "integer", "资源 id,来自 resource.search"))
|
||||
.readAt("/resource"));
|
||||
|
||||
list.add(ToolDef.of("resource.categoryTree", MODULE, "资源分类树",
|
||||
"资源分类树(学段 → 学科 → 年级册次 → 章节),用于按分类筛选资源。",
|
||||
"GET", "/api/category/Tree")
|
||||
.readAt("/resource"));
|
||||
|
||||
list.add(ToolDef.of("resource.collect", MODULE, "收藏资源",
|
||||
"收藏或取消收藏一份资源。",
|
||||
"POST_FORM", "/api/resource/Collect")
|
||||
.p(ToolParam.required("id", "integer", "资源 id")
|
||||
.label("资源"))
|
||||
.write("/resource/collect"));
|
||||
|
||||
list.add(ToolDef.of("resource.textbookOptions", MODULE, "教材选项",
|
||||
"查询可选的教材版本 / 学科 / 出版社。",
|
||||
"GET", "/api/textbook/Options")
|
||||
.readAt("/textbook"));
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -109,11 +109,22 @@ agent:
|
||||
browser-exec:
|
||||
enabled: true
|
||||
|
||||
# ★ 角色映射:按本校 UserBase 角色体系校准(BoaUser.type=1 恒为管理员)
|
||||
# ★ 角色映射:按本校用户中心(UserBase)「用户身份」字典实测校准 ★
|
||||
# 平台身份号 = 门户顶栏 / GetUserInfo 的 currentRole.roleId(采样 200+ 账号取得):
|
||||
# 1 = 老师 2 = 校领导 3 = 学生 4 = 家长 5 = 局领导 6 = 工作号 7 = 管理员
|
||||
# 映射到助手角色:1/6 → 教师,3 → 学生,4 → 家长,2/5/7 → 管理员
|
||||
# ⚠️ 此前默认(student=1 / teacher=2,3 / admin=4..7)是猜的,把 roleId=1 当成学生,
|
||||
# 于是「李晶(老师)」在助手里被显示成「学生」——这是本次修正的根因。
|
||||
roles:
|
||||
student: [1] # 学生
|
||||
teacher: [2, 3] # 教师 / 班主任
|
||||
admin: [4, 5, 6, 7] # 校管 / 分管领导 / 教务 / 校长
|
||||
student: [3] # 学生
|
||||
teacher: [1, 6] # 老师 / 工作号(教职工)
|
||||
parent: [4] # 家长
|
||||
admin: [2, 5, 7] # 校领导 / 局领导 / 管理员
|
||||
# 账号既无「当前身份」、也没挂已识别角色号时的兜底口径(按 BoaUser.type)
|
||||
student-user-types: [0] # 学生
|
||||
teacher-user-types: [2] # 教职工
|
||||
admin-user-types: [1] # 平台超管
|
||||
parent-user-types: [] # 家长(平台暂未见稳定口径,留空待校准)
|
||||
admin-also-teacher: true # 管理员同时拥有教师侧能力
|
||||
|
||||
# --- 业务模块基地址(key 必须与工具定义里的 MODULE 常量一致)---
|
||||
@@ -124,7 +135,6 @@ agent:
|
||||
dormnotice: http://base.yunhaixingtong.com/dormnotice
|
||||
familyactivity: http://base.yunhaixingtong.com/familyactivity
|
||||
coursehomework: http://base.yunhaixingtong.com/coursehomework
|
||||
resourcelibrary: http://base.yunhaixingtong.com/resourcelibrary
|
||||
profession: http://base.yunhaixingtong.com/profession
|
||||
|
||||
# --- 模块默认落地页(深链兜底)---
|
||||
@@ -139,7 +149,6 @@ agent:
|
||||
dormnotice: /par/notices # 宿舍通知箱
|
||||
familyactivity: /par/activities # 活动广场
|
||||
coursehomework: /stu/today # 今日作业
|
||||
resourcelibrary: /resource # 资源管理
|
||||
profession: /home # 发展首页
|
||||
|
||||
# 密钥链验签依赖 Redis(sign:app:*)。关掉 Redis 健康指标:Redis 抖动不应把 /actuator/health
|
||||
|
||||
Reference in New Issue
Block a user