★「通知公告」与既有「校园公告」是两个应用,不是同一个: · 校园公告 CampusAnnouncement → key=campusnotice、前缀 /campusnotice、按班级下发、带审批流/草稿箱(既有 notice.*) · 通知公告 NoticeFront → key=notice、前缀 /notice、按用户下发,无审批/草稿/推送范围(本次新增 notify.*) 两者路由与页面名几乎同名(/list、/list/new、已收到/已发送),极易拿错源码,故工具前缀避开已占用的 notice.*。 新增 NoticeTools(9 个工具):收件箱/详情/一键已读、发布/编辑/我发出的/阅读情况、发文部门字典、组织树。 发布表单逐项对齐 NoticeFront/src/views/notice/NewNotice.vue#doAdd: title / content / deptId / receiveList / fileIds / timingSendTime (smsFlag 在页面里没有对应控件、恒为 0,故不放出;receiveList 的「全部用户」哨兵是 all。) 配套:ToolRegistry 注册、RolePolicy 把发布闭环与两个字典工具列为教职工专属、 application.yml 补地址 http://base.yunhaixingtong.com/notice 与默认落地页 / (AgentSettings 出厂默认表也要补 notice —— 契约测试用的是 new AgentSettings(),不读 yml)。 fix(ToolExecutor): 已按 joinSeparator 拼成逗号串的字段不再被包回数组 normalizeJsonArgs 的第二个循环「数组参数给了标量 → 包成单元素数组」会作用到 刚拼好的 receiveList/fileIds 上,把 101,102 变成 [101,102], 而模块侧 NoticeRequest.receiveList 是 String ⇒ 直接判非法。 此前一直没暴露:本地 mock 的提交体是原样 JSON.stringify(args)(本来就是数组), 看不出差异,只有真实后端才走到这一步。现在 join 过的字段直接跳过该循环。 测试:ModuleFormParityTest 新增「通知公告发布字段集不与校园公告互串」+ 「代取地址带 /notice 前缀」+「提交体是逗号串、哨兵互斥、提交路径带前缀」;全量 126/126 绿。
- 角色字典实测校准(采样 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 通过
- com.yunhai.agent,端口 8093,context-path /agent,制品 target/agent.jar;与 NoticeService 同构 - CAS 单点登录 + 三层角色权限(学生/教师/管理员/访客)+ 会话与工具调用审计落库 - DeepSeek 大模型编排 + 7 个业务模块工具(请假/公告/宿舍/活动/作业/资源库/教师发展) - 浏览器代执行协议(服务端挂起 → 前端用登录态代调 → toolResult 续跑)+ 调用失败深链兜底 - 登出修复:服务端真正 session.invalidate() + 前端两步登出 + logout-guard - 保留 projman 注入的 .gitea/workflows/build.yml 与 docker/Dockerfile;docker/application-prod.yml、run-app.sh 随工程入库