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 / scopes / flow / radio / switch / richtext / userpicker */ private String widget; /** 数据类型:string / integer / number / boolean / array */ private String type; /** * 数组值的序列化分隔符(仅 POST_JSON 有意义)。 *
前端展示时不需要它(用户看到的是多选),但下发给前端便于「提交前预览」如实呈现最终值。 */ private String joinSeparator; /** * {@code widget=file} 时的上传地址(相对站点根),如 {@code /dormnotice/api/base/FileUpload}。 *
模块的附件上传只认浏览器 CAS 会话,必须由前端带用户登录态 POST(multipart), * 拿到 {@code data.fileid} 后作为 fileIds 提交。 */ private String uploadPath; /** {@code widget=file} 时是否允许多个附件 */ private boolean multiple; /** * {@code widget=richtext}(富文本正文)时,「插入图片」的上传地址(**已带模块前缀**的绝对相对路径), * 如 {@code /notice/api/file/UploadImage}。 *
与附件同理:模块的上传接口只认浏览器 CAS 会话,必须由前端带用户登录态 POST(multipart)。
*/
private String richTextUploadPath;
/**
* {@code widget=richtext} 时,正文内图片的预览地址模板(**已带模块前缀**,含 {@code {id}} 占位),
* 如 {@code /notice/api/file/Preview?id={id}} —— 前端拿到上传返回的文件 id 后替换占位符,
* 得到可直接放进 {@code } 的地址。
*/
private String richTextPreviewPath;
/**
* {@code widget=userpicker}(通知对象)的**数据源页签**,形如
* {@code [{name:"基础平台", call:{...}}, {name:"自定义组", call:{...}}]}。
*
*
搬运自通知公告模块页 {@code components/UserCheckModal.vue} 的两个页签,
* 每个 {@code call} 都已经是「**带模块前缀**的浏览器代取调用」(同 {@link #optionCall} 的形态),
* 由前端用用户登录态去取原始**嵌套树**(不做拍平 —— 拍平会丢掉层级,树就画不出来)。
*/
private List 前端把它作为多选的第一个选项;用户只勾它 → 提交 {@code ["ALL"]};
* 同时勾了具体项 → 提交时折叠掉它,以具体项为准。
*/
private String allToken;
/** 「全部」选项的显示名 */
private String allTokenLabel;
/**
* {@code widget=scopes} 时的节点类型(校园公告 pushScopes):
* 1 全校 / 2 学部 / 3 年级 / 4 班级 / 5 训练队 / 6 指定学员。
* 前端把多选结果拼成 {@code [{scopeType,scopeId,scopeName}]}。
*/
private Integer scopeType;
/**
* 「镜像字段」:本字段不由用户填写({@code hidden}),提交时自动填入同一表单中
* {@code mirrorOf} 指定字段**选中项的显示名**。
*
* ★ 用途:公告/宿舍/活动三个模块页在提交时会用字典把部门 id 反查成名称一并发出
* ({@code deptId} + {@code deptName},后端字典缺失时回退该名称)。助手只有下拉选中的 id,
* 但前端手里就有选项的 label —— 由它顺手镜像过去,提交体才和模块页一模一样。
*/
private String mirrorOf;
/**
* 「连续请假」展开说明:{@code {count: 天数字段, start: 开始时间字段, end: 结束时间字段}}。
*
* 作用在请假工具上:当本字段({@code continuousLeave})取 1 时,前端按
* {@code continuousLeaveNum} 天把 {@code startDate}/{@code endDate} 复制成逐天时间段,
* 生成模块要的 {@code continuousLeaveTime}({@code [{startDate,endDate}]})——
* 与模块页 {@code LeaveTimeSection.regenerate()} 的口径一致。
*/
private Map 作业模块(coursehomework V2)的 {@code attachments} 形如
* {@code [{fileId,fileUrl,fileType,fileName,sort}]},与其余模块的 {@code fileIds="1,2"} 不同,
* 故由前端按上传结果组装成对象。
*/
private boolean fileAsObject;
/**
* 单选控件({@code widget=radio})在选项就绪后自动选中第一项。
* 对齐模块页:{@code LeaveApply.vue} 的「请假类型」一进页面就已选中第一个类型。
*/
private boolean autoPickFirst;
/**
* 选项只有一个时自动填入并隐藏本字段。
* 对齐模块页:{@code LeaveApply.vue} 的「班级」用 {@code v-if="myClasses.length > 1"}`,
* 单班时不渲染、值直接带上。
*/
private boolean hideWhenSingleOption;
/**
* 快捷时段按钮组:{@code {start: 开始字段名, end: 结束字段名,
* items: [{label, start, end}]}};{@code start/end} 为时刻({@code HH:mm:ss})。
* 对齐模块页 {@code LeaveTimeSection.quickSet()}:沿用已选日期,只换时分秒。
*/
private Map 用于对齐业务模块页的原文案,如请假事由的「请输入请假原因.....」——
* 这里不该塞它的示例值(「发烧就医,需在家休息」),那是给模型看的参考,不是给用户看的提示。
*/
private String placeholder;
private String defaultValue;
/**
* 下拉选项的动态来源(字典工具名,如 leave.types)。
* 有值但 {@link #options} 为空 ⇒ 字典接口没取到(多半是下游 302/超时),
* 前端据此提示用户「可先手填编号」,而不是干瞪眼。
*/
private String optionsFrom;
/**
* 当前 {@link #options} 是否来自内置兜底(而非学校实时字典)。
* 为 true 时前端提示「用的是标准类型,自定义类型暂时没取到」,而不是静默当成权威值。
*/
private boolean optionsFallback;
/** 下拉选项 [{value,label}] */
private List