把 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 项断言全绿
31 KiB
校园智能助手 · 五模块能力盘点与工具补全建议
盘点日期: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 的业务判定,统一靠三件事:
- 平台菜单授权
GET /api/base/GetUserMod—— 决定"能不能进这个入口页"(modId是稳定契约); - URL 前缀 ——
/par/*= 家长端、/stu/*= 学生端,其余 = 教职工端(roleOfPath()); - 后端数据范围 —— 同一接口按身份收敛(学生看自己 / 教师看任教班 / 管理员看全校)。
| 模块 | 端分离方式 | 入口 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