build / build-push (push) Successful in 54s
原来助手表单只渲染"缺失的必填项",且控件只有文本/单选/时间 —— 与各模块 自己的发布页相比缺了接收对象多选、附件、定时发送、置顶、紧急程度、回执单据、 发布方式等字段,用户没法"填得一样"。 补齐一层共享的表单能力,再把三个发布工具按模块页逐字段重写: 共享能力 - ToolParam: 新增 join(分隔符)/multiple/allOption(哨兵)/scopes(推送范围), array 类型有选项来源时自动用多选控件;数组 schema 补 items - ToolDef: 新增 fullForm() —— 表单渲染全部字段(不再只渲染缺失必填) - ToolExecutor: POST_JSON 前按 joinSeparator 把数组拼成模块要的逗号串; allToken 与具体项互斥(只选具体项→拼串,否则发哨兵) - AgentOrchestrator: file 控件补 uploadPath(/<模块>/api/base/FileUpload) - 模板/参数文件同步下发 joinSeparator/uploadPath/multiple/allToken/scopeType 三个发布工具 - notice.publish: 补重要程度/接收班级(pushScopes 对象数组)/置顶/短信/阅读回执/ 附件/定时发送/发布方式;新增 notice.stuTree(组织树) - dorm.publish: 补紧急程度/生效时间/回执截止/回执单据/接收宿舍(多选,ALL)/ 宿管配合/置顶/短信/附件/定时发送/存草稿 - activity.publish: 补报名截止/回执方式三档/名额上限/家长随行/活动费用/ 接收班级(多选,ALL)/短信/附件/定时发送/存草稿 - leave.submit/register: 连续请假改为可填参数,补连续天数与佐证材料附件 测试:发布工具契约 + 表单字段与模块页一致性断言;90 tests 全绿
106 lines
4.1 KiB
Java
106 lines
4.1 KiB
Java
package com.yunhai.agent.tool;
|
||
|
||
import lombok.Data;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 表单里的一个字段:由 {@link ToolParam} 生成,前端据此选择控件(下拉 / 日期时间 / 多行文本…)。
|
||
*/
|
||
@Data
|
||
public class FormField {
|
||
|
||
/** 提交时的参数名(与业务接口一致) */
|
||
private String name;
|
||
|
||
/** 中文标签,如「开始时间」 */
|
||
private String label;
|
||
|
||
/** 控件类型:text / textarea / number / date / datetime / select / multiselect / file */
|
||
private String widget;
|
||
|
||
/** 数据类型:string / integer / number / boolean / array */
|
||
private String type;
|
||
|
||
/**
|
||
* 数组值的序列化分隔符(仅 POST_JSON 有意义)。
|
||
* <p>前端展示时不需要它(用户看到的是多选),但下发给前端便于「提交前预览」如实呈现最终值。
|
||
*/
|
||
private String joinSeparator;
|
||
|
||
/**
|
||
* {@code widget=file} 时的上传地址(相对站点根),如 {@code /dormnotice/api/base/FileUpload}。
|
||
* <p>模块的附件上传只认浏览器 CAS 会话,必须由前端带用户登录态 POST(multipart),
|
||
* 拿到 {@code data.fileid} 后作为 fileIds 提交。
|
||
*/
|
||
private String uploadPath;
|
||
|
||
/** {@code widget=file} 时是否允许多个附件 */
|
||
private boolean multiple;
|
||
|
||
/**
|
||
* 「全部」哨兵值(如 {@code ALL})与其显示名(如「全部宿舍」)。
|
||
* <p>前端把它作为多选的第一个选项;用户只勾它 → 提交 {@code ["ALL"]};
|
||
* 同时勾了具体项 → 提交时折叠掉它,以具体项为准。
|
||
*/
|
||
private String allToken;
|
||
|
||
/** 「全部」选项的显示名 */
|
||
private String allTokenLabel;
|
||
|
||
/**
|
||
* {@code widget=scopes} 时的节点类型(校园公告 pushScopes):
|
||
* 1 全校 / 2 学部 / 3 年级 / 4 班级 / 5 训练队 / 6 指定学员。
|
||
* <p>前端把多选结果拼成 {@code [{scopeType,scopeId,scopeName}]}。
|
||
*/
|
||
private Integer scopeType;
|
||
|
||
private boolean required;
|
||
|
||
/** 说明(来自工具定义,写清格式与含义) */
|
||
private String description;
|
||
|
||
/** 格式示例,前端用作 placeholder,如 2026-10-11 08:00:00 */
|
||
private String example;
|
||
|
||
private String defaultValue;
|
||
|
||
/**
|
||
* 下拉选项的动态来源(字典工具名,如 leave.types)。
|
||
* <p>有值但 {@link #options} 为空 ⇒ 字典接口没取到(多半是下游 302/超时),
|
||
* 前端据此提示用户「可先手填编号」,而不是干瞪眼。
|
||
*/
|
||
private String optionsFrom;
|
||
|
||
/**
|
||
* 当前 {@link #options} 是否来自内置兜底(而非学校实时字典)。
|
||
* <p>为 true 时前端提示「用的是标准类型,自定义类型暂时没取到」,而不是静默当成权威值。
|
||
*/
|
||
private boolean optionsFallback;
|
||
|
||
/** 下拉选项 [{value,label}] */
|
||
private List<Map<String, String>> options = new ArrayList<>();
|
||
|
||
/* ==================== 动态选项(浏览器代取 + 联动) ==================== */
|
||
|
||
/**
|
||
* 「浏览器代取选项」的调用描述:业务模块的字典接口(班级、学生名单…)只认浏览器 CAS 会话,
|
||
* 服务端代取必然 302,所以把地址下发前端,由前端用**用户自己的登录态**取回原始字典再渲染下拉。
|
||
*
|
||
* <p>地址串里可能含 {@code {{字段名}}} 占位符(见 {@link #dependsOn}),
|
||
* 前端在依赖字段有值时做替换(值需 URL 编码)后才发起请求。
|
||
*/
|
||
private com.yunhai.agent.model.BrowserToolRequest.BrowserCall optionCall;
|
||
|
||
/** 本字段选项依赖的先序字段名(如「学生」依赖「班级」);依赖未填时前端应清空并提示先选 */
|
||
private List<String> dependsOn = new ArrayList<>();
|
||
|
||
/** 从字典返回对象里取哪个字段作为选项「值」(如 classId / stuId) */
|
||
private String valueKey;
|
||
|
||
/** 从字典返回对象里取哪个字段作为选项「显示名」(如 className / stuName) */
|
||
private String labelKey;
|
||
}
|