Files
yunhai-agent-service/docs/模块能力盘点与工具补全建议.md
T
lijing c16356db6e
build / build-push (push) Successful in 1m2s
feat(form): 发布表单与各模块「新建发布」页逐字段对齐(含审批流与作业两步发布)
把 5 个模块「新建/发布」页的字段与提交体逐个核对后,补齐此前缺失或形态不符的部分:

- 部门名镜像:公告/宿舍/活动三处在模块页是「字典 id + 反查名称」一起提交。
  新增 mirrorLabelOf 机制 —— 该字段不渲染控件、不进模型 schema,提交时按源字段
  选中项的显示名填充(deptName)
- 公告审批流:新增 flow 控件(widget=flow)+ 教师组织树字典 notice.teaTree,
  提交 flow:[{name,vote,approverTeaIds}];publishType 值域修正为 direct/approve;
  存草稿改用模块自己的独立接口 notice.saveDraft(POST /api/notice/SaveDraft)
- 活动分类:category 提交的是**分类名称**(模块页 :value="String(c.v)"),
  optionsKeys 由 ("k","v") 改为 ("v","v")
- 请假附件:fileIds 在 HomeLeave 是 number[](JSON 数组),去掉逗号串拼接;
  连续请假按 continuousLeaveNum 逐天展开成 continuousLeaveTime[](服务端/浏览器同源)
- 作业发布(整块新增):homework.publish / schedule / published / drafts /
  teachingSubjects / classTree。模块没有一步发布的接口,用 ToolDef.then 声明两步提交
  (Create 落草稿 → Publish | Schedule);附件是对象数组
  attachments:[{fileId,fileUrl,fileType,fileName,sort}],上传走 file 域
  /coursehomework/api/file/Upload
- 执行器:新增 followUp 两步提交(浏览器侧同源)、数组参数给标量时包成单元素数组、
  首步响应 data 取资源 id(对象形态取 .id,避免拼出 /homeworks/{"id":1}/publish)
- 新增 ModuleFormParityTest(13 项)逐条锁住上述契约

回归:mvn clean package → Tests run: 103, Failures: 0, Errors: 0, BUILD SUCCESS
真机:headless Chrome 走「表单 → 浏览器代执行 → 模块接口」,50 项断言全绿
2026-10-13 11:29:03 +08:00

31 KiB
Raw Blame History

校园智能助手 · 五模块能力盘点与工具补全建议

盘点日期:2026-10-12 范围:AgentService 已对接的 5 个业务模块(请假 / 校园公告 / 宿舍通知 / 家校活动 / 课程作业) 方法:逐模块通读前端 src/api/module/*.ts + src/router/routes.ts + 权限守卫,与 AgentService 现有 tool/defs/*.java 做差集。 目标:① 说清每个模块的功能与权限怎么划;② 指出哪些写操作可以做成表单;③ 挖出模块有、助手还没接的能力。


0. 结论速览

模块 已接工具 建议新增 一句话结论
homeleave 请假 12 +6 最完整的一个,缺的是「删除 / 类型字典维护 / 按班查列表」
campusnotice 校园公告 9 +14 发得出,但收不回——撤回/置顶/催读/阅读情况全缺
dormnotice 宿舍通知 9 +18 家长侧齐了,管理侧几乎空白;模块还自带一整套「床位上床台账」完全没接
familyactivity 家校活动 7 +13 家长报名齐了,学校侧(发活动 / 确认报名)全缺
coursehomework 课程作业 4 +20 缺口最大:只接了学生端,教师端一整套能力 0 接入
合计 41 +71 —
(profession 教师专业发展,教师专属,附带参考) 9 +12 只缺「编辑/删除记录、评论点赞、统计报表」

一句话总纲:四个「发布型」模块(公告 / 宿舍 / 活动 / 作业)其实是同一套骨架—— 我发布的 → 全部 → 详情 → 新建/编辑 → 回执或提交名单 → 统计 → 应用设置, 再各自加一个 /par/* 家长端或 /stu/* 学生端。 助手目前普遍只做了**「读列表 + 我提交」这一层, 而骨架里价值最高的「发布 / 撤回 / 盯回执 / 批阅 / 催办」**基本没接。


1. 先说权限:能力边界的四层判定

1.1 助手侧(AgentService)

层 组件 作用
1 RoleResolver 只读平台 BoaUser,只认「当前身份」currentRole(不做并集)→ 教师 / 学生 / 家长 / 管理员 / 访客
2 ToolRegistry 只把本身份可见的工具写进模型 schema —— 模型"看不见"就不会选错
3 ToolExecutor 调用前再校验一次,越权直接拒绝并打 [越权拦截]
4 浏览器代执行(A 通道) 写操作由前端带用户登录态执行,服务端不代持身份

RolePolicy 现状(一张集中表):

  • STAFF_ONLY(教师+管理员):请假登记/审批/统计/批量通过、公告已发/发文部门/发布/审批、宿舍楼栋房间、活动班级树
  • STUDENT_ONLY:作业四件套、请假申请、销假
  • STUDENT_OR_PARENT:活动报名 / 取消报名
  • SHARED:撤销请假
  • 未列入任何名单 = 所有已识别角色都可用

★★ 最大风险点:新增工具若忘了登记,默认是"人人可用"。 例如把 homework.review(教师打分)漏登记,学生就会在目录里看到"给作业打分"。 本报告第 5 节给出建议分桶表,实施时必须同步改 RolePolicy。

1.2 模块侧(5 个前端怎么分权限)

结论:五个模块的前端都几乎不做基于 roleId 的业务判定,统一靠三件事:

  1. 平台菜单授权 GET /api/base/GetUserMod —— 决定"能不能进这个入口页"(modId 是稳定契约);
  2. URL 前缀 —— /par/* = 家长端、/stu/* = 学生端,其余 = 教职工端(roleOfPath());
  3. 后端数据范围 —— 同一接口按身份收敛(学生看自己 / 教师看任教班 / 管理员看全校)。
模块 端分离方式 入口 modId 契约
homeleave 纯菜单(无 URL 前缀) 2 申请 / 3 我的 / 4 审批 / 5 登记 / 6 统计 / 7 设置
campusnotice 纯菜单 1 我的公告 / 2 已发管理 / 3 全部公告 / 4 统计 / 5 审批中心 / 21 设置
dormnotice /par/* 2 我发的 / 3 全部 / 25 回执情况 / 4 统计 / 21 设置 ‖ 31 通知箱 / 32 我的回执
familyactivity /par/* 2 我发的 / 3 全部 / 25 报名情况 / 4 统计 / 21 设置 ‖ 31 活动广场 / 32 我的报名
coursehomework /stu/* 教师端无 /stu 前缀(列表/详情/提交情况/批改中心/统计);学生端 今日作业 / 待订正 / 详情

注意:/list/new、/list/detail、/signups、/grade 这类二级落地页一律不判权限(只要路由声明了 meta.parentId)。 所以"有权限发公告"≠"有权限进审批中心",两者是不同 modId。


2. 逐模块盘点

图例:角色 = 建议归属(学/教/管 = 学生/教师/管理员,家 = 家长);类型 = 只读 / 单参写 / 表单写。 ⭐ = 高频高价值,建议优先。

2.1 homeleave 请假 —— 已接 12,建议 +6

已接:leave.types myClasses classStudents myLeaves detail stats submit(学生申请) register(教师登记) withdraw reportBack audit batchPass

模块能力全景(/api/leave/* + /api/dict/* + /api/leavestats/*):

页面 角色 能力
/apply 请假申请 学生 选班级/类型/时间/事由/附件 → 提交
/my 我的请假 学生 列表+筛选、详情、撤销、申请销假
/audit 请假审批 教师/管理员 列表、批量通过、本班一键通过、通过/拒绝、撤销审批、销假审批、删除
/register 请假登记 教师/管理员 选班级→学生→类型→时间 → 免审登记
/stats 请假统计 教师/管理员 时间/班级/类型筛选 + 分布
/setting 应用设置 管理员 请假类型字典增删改启停排序

建议新增:

建议工具 接口 角色 类型 说明
leave.delete ⭐ POST /api/leave/Delete?id= 教/管 单参写 只允许删「已撤销/已销假/已拒绝」;补全审批页的删除
leave.typeList GET /api/dict/LeaveTypeList 管 只读 含停用项的管理列表(现有 leave.types 只有启用项)
leave.typeAdd POST /api/dict/LeaveTypeAdd?name= 管 表单写 "加一个『竞赛假』"
leave.typeUpdate POST /api/dict/LeaveTypeUpdate?serid=&name=&enable= 管 表单写 改名 / 启停
leave.typeDelete POST /api/dict/LeaveTypeDelete?serid= 管 单参写 被引用时后端会拒绝(要有友好提示)
leave.typeSort POST /api/dict/LeaveTypeSort?ids= 管 单参写 调整下拉顺序
(扩展)leave.myLeaves 同上,加 classId/stuId/type 参数 教/管 只读 现在教师问"三班今天有谁请假"没法筛

说明:leave.stats / audit / batchPass 已有,是五个模块里做得最完整的一个。


2.2 campusnotice 校园公告 —— 已接 9,建议 +14

已接:notice.received readTabCount sent detail deptDics publish approvalList approve reject

模块能力全景:

页面 角色 能力
/ 我的公告 全员 收件箱、未读/已读筛选、一键已读、上/下篇、打印、附件
/list 已发管理 发布者 撤回 / 置顶 / 催读 / 转发 / 编辑重提 / 删除 / 阅读回执
/list/new 写公告 发布者 富文本+附件+置顶+短信+阅读回执+定时发送;直接发布 / 存草稿 / 提交审批
/drafts 草稿箱 发布者 继续编辑、提交审批、删除
/noticelist 全部公告 管理员 全量查询 + 删除
/approval 审批中心 审批人 待审/已通过/已驳回/全部 + 通过/驳回 + 审批轨迹
/setting 应用设置 管理员 发文部门字典 + 自定义联系组

建议新增:

建议工具 接口 角色 类型 说明
notice.revoke ⭐ POST /api/notice/UserPull?serid= 教/管 单参写 "发错了,撤回"
notice.setTopmost ⭐ POST /api/notice/SetTopmost?serid=&topmost= 教/管 单参写 置顶 / 取消
notice.expedite ⭐ POST /api/notice/Expedite?serid= 教/管 单参写 催读,管理刚需
notice.readDetail ⭐ GET /api/notice/ReadDetail?serid= 教/管 只读 谁读了 / 谁没读(教师维度分组)
notice.readReceipt GET /api/notice/ReadReceipt?serid= 教/管 只读 年级→班级→学生 + 教师组的回执快照
notice.readAll POST /api/notice/InitializeRed 全员 单参写 一键全部已读("我还有多少没看"→顺手清)
notice.delete POST /api/notice/Delete 教/管 单参写 body 是 id 数组,支持批量
notice.drafts GET /api/notice/DraftList 教/管 只读 草稿箱
notice.saveDraft POST /api/notice/SaveDraft 教/管 表单写 先存着
notice.edit POST /api/notice/Edit 教/管 表单写 编辑(flow=[] 清流程)
notice.submitApproval ⭐ POST /api/notice/Submit 教/管 表单写 提交审批,steps[].approverTeaIds 来自教师树
notice.appendReceivers POST /api/notice/ReceiveUsers?serid=&users= 教/管 单参写 追加接收人(补发)
notice.stats GET /api/notice/Statis 管 只读 区间统计(页面 /stats 目前还是占位页,但接口是活的)
notice.deptManage /api/dict/{ManageList,Add,Update,Delete,Sort} 管 写 发文部门维护

老师最常问的两句是「这条通知谁还没看」和「催一下没看的」,对应 readDetail + expedite,建议 P0。


2.3 dormnotice 宿舍通知 —— 已接 9,建议 +18(缺口第二大)

已接:dorm.myNotices myNotice sendList submitReceipt cancelReceipt buildings rooms roomStudents dormTree

模块能力全景(三条业务线):

页面 角色 能力
/par/notices /par/mine 家长 通知箱、阅读、提交/修改/取消回执
/list /noticelist /list/new 宿管/教师 发布通知(含回执方式/回执单据/接收宿舍/短信/定时)、撤回、置顶、催办、编辑
/receipts 回执情况 宿管/管理员 回执名单(按楼栋·房间)、代为确认 / 取消 / 退回、催办、导出 CSV
/setting 宿舍设置 管理员 通知类型字典、发布部门字典、楼栋/房间台账 + 住宿生床位安排、自定义联系组

建议新增(A. 通知管理侧):

建议工具 接口 角色 类型 说明
dorm.publish ⭐ POST /api/notice/Create 教/管 表单写 宿管发通知。字段:标题/类型/部门/紧急度/生效时间/回执截止/回执方式(none/confirm/fill)/回执单据(stay/visit/adjust/general)/接收宿舍/附件
dorm.edit POST /api/notice/Edit 教/管 表单写 编辑(含 sourceId)
dorm.revoke POST /api/notice/UserPull?serid= 教/管 单参写 撤回
dorm.setTopmost POST /api/notice/SetTopmost?serid=&topmost= 教/管 单参写 置顶
dorm.delete POST /api/notice/Delete 教/管 单参写 批量删除(级联删回执)
dorm.receipts ⭐ GET /api/notice/Receipts?serid=&status= 教/管 只读 回执名单 + 汇总(应收/已回/已确认/已填报/未回执/回执率)
dorm.receiptDetail GET /api/notice/ReceiptDetail?receiptId= 教/管 只读 单条回执详情
dorm.reviewReceipt ⭐ POST /api/notice/Review 教/管 单参写 {receiptId, action: confirm/cancel/reset} —— 代确认 / 取消 / 退回
dorm.remindReceipt ⭐ POST /api/notice/Remind?serid= 教/管 单参写 催未回执家长
dorm.remindStudent POST /api/notice/RemindStudent?serid=&studentId= 教/管 单参写 定向催某个学生
dorm.markRead POST /api/notice/MarkRead?serid=&studentId= 教/管 单参写 代标记已读(线下已通知的情况)
dorm.exportReceipts GET /api/notice/ExportReceipts?serid= 教/管 只读 导出 CSV(返回文本,可回传前端下载)
dorm.stats GET /api/notice/Statis 教/管 只读 通知统计
dorm.formTemplates GET /api/notice/FormTemplates 教/管 只读 回执单据模板(动态字段:key/label/type/required/options)
dorm.noticeTypes GET /api/dict/List?type=noticeType 教/管 只读 通知类型下拉

建议新增(B. 床位台账 —— 模块自带的"没想到的能力"):

建议工具 接口 角色 类型 说明
dorm.pendingStudents ⭐ GET /api/dorm/PendingStudents?keyword=&gender= 教/管 只读 待安排床位学生池
dorm.assignStudent ⭐ POST /api/dorm/AssignStudent?roomId=&studentIds= 教/管 表单写 安排入住(房间 + 学生多选)
dorm.removeStudent POST /api/dorm/RemoveStudent?roomId=&studentId= 教/管 单参写 退宿
dorm.transferStudent POST /api/dorm/TransferStudent 教/管 表单写 调整宿舍(回显是否原宿舍长 + 床位号)
dorm.setMonitor POST /api/dorm/SetMonitor?roomId=&studentId= 教/管 单参写 设/取消宿舍长(取消传 0)
dorm.addBuilding POST /api/dorm/AddBuilding 管 表单写 新增楼栋(可批量铺房间:层数×每层房间数×床位数)
dorm.editBuilding / dorm.delBuilding 同名接口 管 写 改 / 删(删除需先清空房间)
dorm.addRoom / editRoom / delRoom 同名接口 管 写 房间增删改
dorm.buildingTree 组合 BuildingList → RoomList(buildingId) 教/管 只读 楼栋→楼层→房间三级(前端按 floor 分组)

这三条联动链是模块里最有价值、也最"没人想到助手能做"的部分: 楼栋 → 房间 → 住宿生、待安排池 → 安排入住、回执名单 → 代确认/催办。


2.4 familyactivity 家校活动 —— 已接 7,建议 +13

已接:activity.plaza list detail mySignup signup cancelSignup classTree

模块能力全景:闭环 = 发布(草稿/定时/复用)→ 触达(班级定向/短信/置顶)→ 已读追踪 → 报名回执(仅通知 / 需报名 / 需确认)→ 学校确认 / 催办 / 导出 → 统计 → 字典与联系组。

建议新增:

建议工具 接口 角色 类型 说明
activity.publish ⭐ POST /api/activity/Create 教/管 表单写 发活动。字段:标题/分类/主办部门/接收班级/时间地点/回执方式/附件/短信/定时
activity.edit POST /api/activity/Edit 教/管 表单写 编辑
activity.revoke POST /api/activity/UserPull?serid= 教/管 单参写 撤回(家长端不可见)
activity.setTopmost POST /api/activity/SetTopmost 教/管 单参写 置顶
activity.delete POST /api/activity/Delete 教/管 单参写 批量删除
activity.signups ⭐ GET /api/activity/Signups?serid=&signupStatus= 教/管 只读 报名名单(按班级分组 + 汇总)
activity.signupDetail GET /api/activity/SignupDetail?signupId= 教/管 只读 单条回执详情
activity.reviewSignup ⭐ POST /api/activity/Review 教/管 单参写 {signupId, action: confirm/cancel/waitlist, remark} —— 学校确认 / 取消请假 / 待定
activity.remind ⭐ POST /api/activity/Remind?serid= 教/管 单参写 催报名
activity.exportSignups GET /api/activity/ExportSignups?serid= 教/管 只读 导出 CSV 文本(带 BOM)
activity.readDetail GET /api/activity/ReadDetail?serid= 教/管 只读 已读/未读(年级→班级)
activity.stats GET /api/activity/Statis 教/管 只读 活动统计
activity.categories GET /api/dict/List?type=2 全员 只读 活动分类下拉(发布时用)
activity.receiveClasses POST /api/activity/ReceiveClasses?serid=&classes= 教/管 单参写 追加接收班级(补发)

2.5 coursehomework 课程作业 —— 已接 4,建议 +20(缺口最大)

已接(全是学生端):homework.myList detail result submit

★ 这个模块是端分离的:/stu/* = 学生,其余 = 教师。 助手目前只接了 /api/student/homeworks* 四件事,/api/teacher/homeworks/* 一整套 0 接入。 而教师的日常恰恰全在这一侧:布置、催交、批阅、打分、打回。

建议新增(A. 教师端 V2,/api/teacher/homeworks):

建议工具 接口 角色 类型 说明
homework.create ⭐ POST /api/teacher/homeworks 教师 表单写 布置作业(先落草稿)。字段:标题/学科/接收班级/截止时间/提交方式/逾期可补交/截止提醒/附件
homework.editDraft PUT /api/teacher/homeworks/{id} 教师 表单写 仅草稿可改
homework.deleteDraft DELETE /api/teacher/homeworks/{id} 教师 单参写 仅草稿可删
homework.publishNow ⭐ POST .../{id}/publish 教师 单参写 草稿 → 进行中(触发学生通知)
homework.schedule POST .../{id}/schedule 教师 单参写 定时发布 / 取消定时
homework.drafts GET /api/teacher/homeworks/drafts 教师 只读 草稿箱
homework.published GET /api/teacher/homeworks/published 教师 只读 已发布列表(可按学科筛)
homework.remind ⭐ POST .../{id}/remind 教师 单参写 催交:{type: NOT_READ|NOT_SUBMITTED, studentIds?}
homework.extend POST .../{id}/extend 教师 单参写 延长截止(新截止须晚于当前)
homework.copy POST .../{id}/copy 教师 单参写 复制为新草稿
homework.archive POST .../{id}/archive 教师 单参写 归档(只读,不再提醒)
homework.teacherDetail GET .../{id} 教师 只读 作业详情 + 汇总统计 + 分班进度
homework.teacherStats ⭐ GET .../{id}/stats 教师 只读 "这份作业交了多少"
homework.students ⭐ GET .../{id}/students 教师 只读 学生矩阵:谁读了/谁交了/谁没交/谁待批
homework.review ⭐ POST .../{id}/submissions/{studentId}/review 教师 表单写 批阅打分 + 评语(score/comment 至少一项)
homework.returnSubmission ⭐ POST .../{id}/submissions/{studentId}/return 教师 单参写 打回订正(comment 必填)
homework.versions GET .../{id}/submissions/{studentId}/versions 教师 只读 历史提交版本
homework.export GET .../{id}/export 教师 只读 导出学生矩阵 Excel(直链)
homework.subjects GET /api/teacher/homeworks/subjects/teaching 教师 只读 学科下拉
homework.classList GET /api/teacher/homeworks/classes?subject= 教师 只读 年级→班级树,依赖所选学科

建议新增(B. 学生端补全 + 通知中心):

建议工具 接口 角色 类型 说明
homework.withdrawSubmission PUT .../submissions/{submissionId} action=withdraw 学生 单参写 撤回提交(截止前)
homework.resubmit PUT ... action=resubmit 学生 单参写 打回后重交(与 result 配对)
homework.read POST /api/student/homeworks/{id}/read 学生 单参写 阅读上报(幂等)
homework.notifications GET /api/notifications 学生/教师 只读 通知中心(接口已封装但前端无页面,是"有接口无 UI"的隐藏能力)
homework.readAllNotifications POST /api/notifications/read-all 同上 单参写 全部已读

另外 V1 冻结管理端还有 GET /api/homework/SendList(全部人作业)、POST /api/homework/Delete、GET /api/homework/Statis, 供"管理/上级教师"口径使用,可选接。


2.6 profession 教师专业发展(第 6 个模块,教师专属,已接 9,建议 +12)

已接:homeRecords list moduleRecords myRecords detail moduleTree myPoints pointsRank publish

建议工具 接口 类型 说明
profession.editRecord POST /api/profession/Edit 表单写 编辑自己的记录
profession.deleteRecord GET /api/profession/Delete?ids= 单参写 删除
profession.comments GET /api/profession/DiscussList?sid= 只读 评论列表
profession.comment POST /api/profession/DiscussCreate 单参写 发表评论
profession.deleteComment GET /api/profession/DiscussDel?id= 单参写 删评论
profession.like POST /api/profession/LikeCreate?recordId= 单参写 点赞 / 取消(toggle)
profession.timeline GET /api/profession/MyTimeline?userid= 只读 个人时间轴
profession.spaceOverview GET /api/profession/SpaceOverview 只读 个人空间聚合(积分/记录/获赞/被访问)
profession.pointsSource GET /api/profession/PointsSourceList 只读 积分来源明细("我这 20 分怎么来的")
profession.grades / subjects GetGradeList / GetSubList 只读 年级段 / 学科字典(发布记录时用)
profession.stats GET /api/stats/{TeacherStat,ModuleStat,PointsStat} 只读 校级统计(管理员)
profession.modules GET /api/moudule/MouduleList 只读 栏目列表(含 readonly 只读标记)

注:该模块没有审批流(记录发布即生效,isCheck 是栏目启停不是记录审核),别按"提交审核"设计。


3. 跨模块共性缺口 —— "各模块都没想到的能力"

这 7 条是重复出现在多个模块、做一次就能复用多次的能力:

# 共性能力 出现在 助手现状 价值
1 撤回 / 置顶 / 催办三件套 公告、宿舍、活动、作业 全缺 ★★★ 发错了能收回、重要的能置顶、没看的能催 —— 都是单参数 POST,成本极低
2 回执 / 提交名单闭环 公告、宿舍、活动、作业 只做了"我提交",没做"谁没提交" ★★★ 教师最高频诉求
3 统计数据 公告、宿舍、活动、作业都有 Statis 只接了 leave.stats ★★ 一句话出数字
4 字典维护(在"应用设置"里) 公告(发文部门)、宿舍(通知类型)、活动(主办部门/分类)、请假(类型) 只做了"读下拉",没做"改" ★★ 管理员可用自然语言维护
5 附件上传/预览/下载 5 模块统一 /api/file/{Upload,Preview,Down} 写操作暂不支持附件 ★ 侧重点:写时提示"需附件请到页面补传",只读加 Preview/Down 直链
6 级联下拉链 作业、宿舍、活动、公告 基建已有(optionCall + valueKey/labelKey + dependsOn) ★★ 直接复用,见第 4 节
7 审批人选择 公告(多步审批流 steps) 缺 ★ getTeaTree 教师树 + 多选

4. 落地设计:复用现有基建,零新增管线

这一节是"怎么做",全部基于已经跑通的机制:

4.1 写操作 —— 自动走浏览器代执行

服务端无法代持用户登录态调模块 /api/*(下游 CAS 过滤器只认浏览器容器会话,必回 code=302)。 现有 A 通道(commit ab87a4b)已在跑:服务端挂起下发 browserTool.calls → 前端用用户自己的登录态 fetch → 回传结果续跑。 所以上面所有"写"工具,只需要在 ToolDef 里声明 .write(landingPath),不需要任何新的传输管线。

4.2 表单下拉 —— 用现成的 optionCall 机制

后端只下发"取数说明"(含 {{占位符}}),前端带登录态取,再按后端给的 valueKey/labelKey 映射:

ToolParam.required("stuId", "integer", "学生 id")
        .label("学生")
        .optionsFrom("leave.classStudents").optionsKeys("stuId", "stuName")
        .dependsOn("classId");      // ← 选完班级才解锁

需要新写的级联链清单(照这个模式加):

模块 联动链 依赖关系
课程作业 学科 → 年级班级树 homework.classList dependsOn("subject")
课程作业 已发布作业 → 班级 → 学生 stats.byClass → students?classId
宿舍通知 楼栋 → 房间 → 住宿生 RoomList dependsOn("buildingId");RoomStudents dependsOn("roomId")
宿舍通知 楼栋 → 房间(接收宿舍多选) 同上,前端按 floor 分组
家校活动 接收班级(年级→班级) GetClassTree 分组下拉,选"全部班级"→ receiveList=ALL
校园公告 发文部门 / 接收范围 / 审批人 dict/List?type=1 / getStuTree / getTeaTree
请假 班级 → 学生(已完成) 参考实现

4.3 裸意图直达 —— 可扩展

已有 IntentShortcut(去标点 + 剥前后缀正好等于标准说法 + ≤12 字 → 跳过 LLM 直接弹表单)。 可照葫芦画瓢加:

说法 直达工具
「我要交作业」「看今天作业」 homework.myList / 学生提交表单
「布置作业」 homework.create
「我要报名」 activity.signup(先弹活动选择)
「查宿舍」 dorm.myNotices
「发通知」 视模块 → notice.publish / dorm.publish / activity.publish(有歧义,需按目录可见性消歧)

⚠️ 「发通知」「我要报名」这类跨模块同义的说法不要做裸意图直达, 交给模型按 catalog 里可见的工具自己选,否则会猜错模块。


5. 角色分桶建议(实施时必须同步改 RolePolicy)

工具族 建议桶
写:发布/编辑/撤回/置顶/催办/删除/审批/统计/字典维护/床位台账/批阅打分/打回/催交 STAFF_ONLY
写:请假申请、交作业、阅读上报、撤回提交、重交 STUDENT_ONLY
写:活动报名 / 取消报名 STUDENT_OR_PARENT
写:一键全部已读、宿舍回执提交/取消 不限(所有人)
只读:各类列表/详情/统计/下拉 按模块判定(教师专属模块如 profession.* 用前缀规则)

当前 profession.* 已用模块前缀规则(STAFF_MODULE_PREFIXES)整模块归教职工,新增模块可沿用。

几条容易踩的:

  • homework.* 现在被整桶放进 STUDENT_ONLY。新增教师端工具必须改名字或用显式 .allow(...),否则会被误判成学生工具。 建议改成:homework.myList/detail/result/submit/read/...(学生)保留在 STUDENT_ONLY, 而 homework.create/publish/review/... 显式登记 STAFF_ONLY。
  • 「回执/名单查询」(dorm.receipts、activity.signups、notice.readDetail)必须 STAFF_ONLY —— 那是全班/全校数据。
  • 「一键已读」「提交自己的回执」这类只动自己的,不要限制角色。

6. 建议实施顺序(4 批,风险递增)

批次 内容 风险 为什么先做
批 1 只读补全:统计(4 个模块)、阅读情况、回执/报名名单、草稿箱、homework.students 学生矩阵、下拉字典 极低 纯 GET,不改变任何数据;立刻让"谁没交/谁没看"能问
批 2 单参数写:撤回 / 置顶 / 催读 / 催办 / 催报名 / 删除 / 一键已读 / 代确认回执 / 打回 / 归档 / 发布草稿 低 单字段 POST,表单只需"确认";覆盖最高频的"发错了/催一下"
批 3 表单写:布置作业、发活动、发宿舍通知、公告草稿+编辑+提交审批、请假类型字典维护 中 正文级表单,需要完整字段 + 级联下拉
批 4 复杂交互:批阅打分(分数+评语+历史版本)、床位安排(楼栋→房间→学生)、多步审批人选人、导出报表 中高 多步 + 多级联动,建议单独设计交互

附录 A:接口路径速查

# 请假 homeleave
GET  /api/leave/List|Details|MyClasses|ClassStudents   /api/leavestats/Stats
POST /api/leave/Save|Audit|BatchPass|ReportBack        /api/leave/Withdraw|Delete (form)
     /api/dict/LeaveTypeOptions|List|Add|Update|Delete|Sort

# 校园公告 campusnotice
GET  /api/notice/List|SendList|Detail|GetDetail|GetNextPrev|DraftList
     /api/notice/ReadDetail|ReadReceipt|ApprovalList|ApprovalCount|Statis
POST /api/notice/Create|Edit|SaveDraft|Submit|Delete|Approve|Reject (JSON)
     /api/notice/UserPull|SetTopmost|Expedite|InitializeRed|ReceiveUsers (form)
     /api/dict/{List,ManageList,Add,Update,Delete,Sort}  /api/contacts/*

# 宿舍通知 dormnotice
GET  /api/notice/MyNotices|MyNotice|List|SendList|Detail|ReadDetail
     /api/notice/Receipts|ReceiptDetail|ExportReceipts|FormTemplates|Statis
     /api/dorm/BuildingList|RoomList|RoomStudents|PendingStudents   /api/base/GetDormTree
POST /api/notice/SubmitReceipt|CancelReceipt|Create|Edit|Delete|Review (JSON)
     /api/notice/UserPull|SetTopmost|Expedite|Remind|RemindStudent|MarkRead (form)
     /api/dorm/AddBuilding|EditBuilding|DelBuilding|AddRoom|EditRoom|DelRoom
     /api/dorm/AssignStudent|RemoveStudent|TransferStudent|SetMonitor

# 家校活动 familyactivity
GET  /api/activity/MyActivities|List|SendList|Detail|GetDetail|ReadDetail
     /api/activity/Signups|SignupDetail|ExportSignups|Statis|MySignup
POST /api/activity/Signup|CancelSignup|Create|Edit|Delete|Review (JSON)
     /api/activity/UserPull|SetTopmost|Remind|ReceiveClasses|InitializeRed|Expedite (form)
     /api/dict/List?type=1|2   /api/base/GetClassTree

# 课程作业 coursehomework
GET  /api/student/homeworks?tab=      /api/student/homeworks/{id}|/{id}/result
GET  /api/teacher/homeworks/drafts|published|classes?subject=|subjects/teaching|assigned
     /api/teacher/homeworks/{id}|/{id}/stats|/{id}/students|/{id}/export
     /api/teacher/homeworks/{id}/submissions/{studentId}/versions
GET  /api/homework/SendList|Detail|ReadDetail|Statis (V1 管理端)
POST /api/student/homeworks/{id}/read|/{id}/submissions
PUT  /api/student/homeworks/{id}/submissions/{submissionId}   (withdraw|resubmit)
POST /api/teacher/homeworks | /{id}/publish|schedule|remind|extend|copy|archive
     /{id}/submissions/{studentId}/review|return
PUT  /api/teacher/homeworks/{id}      DELETE /api/teacher/homeworks/{id}
GET  /api/notifications               POST /api/notifications/{id}/read|read-all

# 专业发展 profession
GET  /api/profession/HomeModuleRecords|ProfessionList|ModuleRecordList|MyModuleRecordList
     /api/profession/ProfessionDetail|MyTimeline|MyPoints|PointsSourceList|PointsRank
     /api/profession/SpaceOverview|DiscussList|VisitList|GetGradeList|GetSubList
POST /api/profession/Create|Edit|DiscussCreate|DiscussEdit|VisitCreate|LikeCreate
GET  /api/profession/Delete|DiscussDel      /api/moudule/*   /api/points/*   /api/stats/*

# 全模块通用
GET  /api/base/GetUserInfo|GetUserMod|GetSchoolAll|GetClassTree|getStuTree|getTeaTree
POST /api/base/SetRole|FileUpload|Logout
GET  /api/file/Preview|Down|List          POST /api/file/Upload|UploadImage