前端已把 NoticeFront 的 wangEditor 与自绘「通知对象」控件 1:1 搬进助手表单,
后端补上这两个控件所需的契约:
- ToolParam / FormField 新增:
· pickerSources:选人弹窗的**数据源页签**(形如 {name, 模块内相对地址}),
由 AgentOrchestrator 拼上模块前缀后下发(沿用「只写相对路径」的铁律);
· richTextUploadPath / richTextPreviewPath:正文插图的上传与预览地址。
- AgentOrchestrator:把 resolveUploadPath 抽出通用形态 resolveModulePath(幂等、只接受
模块内相对路径);buildForm 为 widget=userpicker 下发 pickerSources;
optionCall 强制改写 widget 的白名单放行 userpicker(否则会被降级成 select)。
- NoticeTools:notify.publish 与 notify.editNotice 的 receiveList 改为 userpicker,
两个数据源为「基础平台」/api/base/GetSchoolAll 与「自定义组」
/api/contacts/GetGroupTree?type=1;content 走 richtext。
测试:NotifyIntentFormTest / IntentDirectFormTest 补 pickerSources 断言
(**只写相对路径**,不带前缀 —— 前缀拼错是本项目反复出过的坑),
ModuleFormParityTest 补 userpicker 取值口径断言(字符串原样透传,不得包成数组)。
mvn -o test:Tests run: 135, Failures: 0, Errors: 0,BUILD SUCCESS。
This commit is contained in:
@@ -539,12 +539,22 @@ class ModuleFormParityTest {
|
||||
// 收件人是「用户」:v-model 为 "all" 或用户 id 逗号串(components/UserCheckInput.vue)
|
||||
ToolParam receive = param(def, "receiveList");
|
||||
assertNotNull(receive, "通知公告按用户下发,必须有 receiveList");
|
||||
// ★ 用 resolveWidget() 而不是 getWidget():receiveList 没有显式 .as("multiselect"),
|
||||
// 它是「type=array + optionsFrom 字典」自然推断出的多选(见 ToolParam#resolveWidget)。
|
||||
assertEquals("multiselect", receive.resolveWidget());
|
||||
// ★ 2026-10-14:控件换成模块页同款的自绘组件(radio 全部/指定 + 选人弹窗),
|
||||
// 故这里是**显式** .as("userpicker"),不再靠 type/optionsFrom 推断。
|
||||
assertEquals("userpicker", receive.resolveWidget(),
|
||||
"通知对象用模块页同款 UserCheckInput(radio 全部用户/指定用户 + 选人弹窗)");
|
||||
assertEquals(",", receive.getJoinSeparator());
|
||||
assertEquals("all", receive.getAllToken(), "勾「全部用户」提交的就是 all");
|
||||
assertEquals("notify.schoolAll", receive.getOptionsFrom());
|
||||
assertEquals("notify.schoolAll", receive.getOptionsFrom(),
|
||||
"弹窗里的组织树仍由 notify.schoolAll 代取(前端取**原始嵌套树**,不拍平)");
|
||||
|
||||
// 正文换成富文本(模块页 NewNotice.vue 用 wangEditor v5),并带上「插入图片」的两个地址
|
||||
ToolParam content = param(def, "content");
|
||||
assertEquals("richtext", content.resolveWidget(), "正文用富文本编辑器");
|
||||
assertEquals("/api/file/UploadImage", content.getRichTextUploadOverride(),
|
||||
"图片上传是独立接口(不是附件的 FileUpload);只写相对路径,前缀由编排层拼");
|
||||
assertEquals("/api/file/Preview?id={id}", content.getRichTextPreviewOverride(),
|
||||
"正文内图片必须用 Preview(inline),Down 是 attachment 内嵌显示不出来");
|
||||
|
||||
// 校园公告那一套字段一个都不该出现在这里
|
||||
assertNull(param(def, "pushScopes"), "pushScopes(推送范围)是校园公告的字段");
|
||||
@@ -620,6 +630,19 @@ class ModuleFormParityTest {
|
||||
assertEquals("101", com.alibaba.fastjson.JSON
|
||||
.parseObject(executor.prepareBrowserCall(def, args).getBody()).getString("receiveList"),
|
||||
"哨兵与具体项互斥:同时选中时具体项优先");
|
||||
|
||||
/* ★ 2026-10-14:前端换成 UserCheckInput 后,表单里存的就是**字符串**("all" / "101,102"),
|
||||
* 不再是数组。这条短路极易出错:normalizeJsonArgs 的第二个循环会把「array 型参数却是标量」
|
||||
* 包成 ["101,102"](整串塞进一个元素),而模块的 NoticeRequest.receiveList 是 String —— 判非法。
|
||||
* 之所以现在没事,是因为第一个循环按 joinSeparator 拼过之后就 continue 了。
|
||||
* 把这个「字符串原样透传」的口径钉住,防止谁把那个 continue 删掉。 */
|
||||
args.put("receiveList", "101,102");
|
||||
assertEquals("101,102", com.alibaba.fastjson.JSON
|
||||
.parseObject(executor.prepareBrowserCall(def, args).getBody()).getString("receiveList"),
|
||||
"userpicker 直接给逗号串时不能再被包成数组");
|
||||
args.put("receiveList", "all");
|
||||
assertEquals("all", com.alibaba.fastjson.JSON
|
||||
.parseObject(executor.prepareBrowserCall(def, args).getBody()).getString("receiveList"));
|
||||
}
|
||||
|
||||
/* ==================== 辅助 ==================== */
|
||||
|
||||
Reference in New Issue
Block a user