build / build-push (push) Successful in 1m2s
把 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 项断言全绿
455 lines
31 KiB
Markdown
455 lines
31 KiB
Markdown
# 校园智能助手 · 五模块能力盘点与工具补全建议
|
||
|
||
> 盘点日期: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` 映射:
|
||
|
||
```java
|
||
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
|
||
```
|