package com.yunhai.agent.tool.defs; import com.yunhai.agent.tool.ToolDef; import com.yunhai.agent.tool.ToolParam; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * 教师专业发展模块工具 —— 后端 Profession,前缀 /api/profession、/api/moudule、/api/points、/api/stats。 * *
★ 发布表单的字段以模块前端源码为**权威契约**: * {@code ProfessionView/src/views/profession/RecordEdit.vue}(发布/编辑记录页)。 * 提交体(模块页 {@code save()} 逐行核对): *
* POST /api/profession/Create (application/x-www-form-urlencoded) * { moduleId, title, grade, subject, ifOpen, remark, * contents: JSON.stringify([{fieldId, value}]), // 栏目动态字段 * fileIds: "11,12" } // 逗号串 *
模块侧的栏目字段接口查询参数叫 {@code SerID},而表单字段叫 {@code moduleId} —— 两边名字不同。 */ private static Map moduleIdAs(String queryParam) { Map m = new LinkedHashMap<>(); m.put(queryParam, "moduleId"); return m; } /** * 「发布 / 编辑记录」页的完整字段。 * * ★ 与 {@code ProfessionView/src/views/profession/RecordEdit.vue} 的表单逐项对齐: * * 标题(必填,≤200) → 年级段 / 学科(两个可空下拉) → 是否公开(单选 公开/不公开) * → 栏目动态字段(按栏目渲染 → contents) → 正文内容(富文本 → remark) → 附件(fileIds) * * 唯一多出来的是「所属栏目」——模块页是从栏目列表点「发布」进来的(栏目由入口决定), * 助手没有这个上下文,所以必须让用户选一次。 */ private static ToolParam[] professionPublishParams() { List ps = new ArrayList<>(); ps.add(ToolParam.required("moduleId", "integer", "栏目 id,来自 profession.moduleTree") .label("所属栏目") .optionsFrom("profession.moduleTree")); ps.add(ToolParam.required("title", "string", "记录标题(200 字以内)") .label("记录标题").placeholder("请输入记录标题").maxLength(200) .eg("2026年秋季公开课教学设计")); ps.add(ToolParam.optional("grade", "string", "年级段,来自 profession.grades") .label("年级段") // 年级段字典是 {value,label}(不是平台通用的 {k,v} / 业务 VO 的 {id,name}),必须指认键名 .optionsFrom("profession.grades").optionsKeys("value", "label")); ps.add(ToolParam.optional("subject", "string", "学科,取值来自 profession.subjects 的 subId") .label("学科") .optionsFrom("profession.subjects").optionsKeys("subId", "subName")); ps.add(ToolParam.optional("ifOpen", "integer", "是否公开:1 公开 / 0 不公开") .label("是否公开").as("radio").dft("1") .options(new String[]{"1", "0"}, new String[]{"公开", "不公开"})); ps.add(ToolParam.optional("remark", "string", "正文内容(对应模块页的富文本编辑器)") .label("正文内容").as("textarea").placeholder("请输入正文内容…")); // 栏目动态字段的打包结果:由表单取回字段定义、渲染后自行生成,用户不直接填 ps.add(ToolParam.optional("contents", "string", "栏目动态字段的取值(JSON 数组,由表单自动生成)") .label("栏目动态字段").hide()); ps.add(ToolParam.optional("fileIds", "array", "附件文件 id 列表(由表单的附件上传得到)") .label("添加附件").as("file").multiple(true).join(",") // ★ 专业发展的附件上传接口与其余模块不同:走 file 域(不是 base/FileUpload)。 // 只写模块内相对路径,前缀由 AgentOrchestrator.resolveUploadPath 拼 → /profession/api/file/Upload // (ProfessionView/src/views/profession/RecordEdit.vue 的 uploadAction = fileUploadUrl) .upload("/api/file/Upload")); return ps.toArray(new ToolParam[0]); } }
★ 与 {@code ProfessionView/src/views/profession/RecordEdit.vue} 的表单逐项对齐: *
* 标题(必填,≤200) → 年级段 / 学科(两个可空下拉) → 是否公开(单选 公开/不公开) * → 栏目动态字段(按栏目渲染 → contents) → 正文内容(富文本 → remark) → 附件(fileIds) *