对齐 ProfessionView/src/views/profession/RecordEdit.vue: - profession.publish 字段改为 moduleId/title/grade/subject/ifOpen/remark/contents/fileIds (POST_FORM /api/profession/Create;附件走 /api/file/Upload;fullForm 全字段渲染) - 新增 4 个字典工具:profession.grades / subjects / moduleFields / areaTree, 并恢复上一轮重写时误删的 profession.myPoints / profession.pointsRank - ToolDef:新增 extraFields* 声明(字典工具 + 参数名 + 「查询参数 → 表单字段」占位符映射 + 前置锚点) - FormRequest:新增 ExtraFields(含 dependsOn / param / before / areaCall) - AgentOrchestrator:抽出共用的 buildReadCall,据此下发 extraFields(栏目字段定义与区划树) - ModuleFormParityTest:新增 4 条契约测试(字段顺序 / 提交方式 / 控件形态 / 动态字段声明)
This commit is contained in:
@@ -28,6 +28,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -761,6 +762,29 @@ public class AgentOrchestrator {
|
||||
form.setMissing(missingLabels);
|
||||
form.setAllFields(def.isFormAll());
|
||||
|
||||
// 「栏目动态字段」(专业发展的栏目自定义字段):构建期枚举不出来,只能把「去哪儿取」
|
||||
// 交给前端带用户登录态取回后就地渲染,提交时打包进 extraFieldsParam(contents)。
|
||||
if (StringUtils.isNotBlank(def.getExtraFieldsFrom())) {
|
||||
// 占位符用**模块侧的查询参数名**(如 SerID),映射告诉前端该拿哪个表单字段去填
|
||||
BrowserToolRequest.BrowserCall call =
|
||||
buildReadCall(def.getExtraFieldsFrom(), def.getExtraFieldsDepends().keySet(), caller);
|
||||
if (call != null) {
|
||||
FormRequest.ExtraFields extra = new FormRequest.ExtraFields();
|
||||
extra.setCall(call);
|
||||
extra.setDependsOn(new LinkedHashMap<>(def.getExtraFieldsDepends()));
|
||||
extra.setParam(def.getExtraFieldsParam());
|
||||
extra.setBefore(def.getExtraFieldsBefore());
|
||||
// 级联字段的区划树(含 {{level}} 占位符,按字段配置取 2 或 3 级)
|
||||
if (StringUtils.isNotBlank(def.getExtraFieldsAreaFrom())) {
|
||||
extra.setAreaCall(buildReadCall(def.getExtraFieldsAreaFrom(),
|
||||
Collections.singletonList("level"), caller));
|
||||
}
|
||||
form.setExtraFields(extra);
|
||||
} else {
|
||||
log.warn("栏目动态字段代取不可用:tool={} dict={}", def.getName(), def.getExtraFieldsFrom());
|
||||
}
|
||||
}
|
||||
|
||||
// 已从对话里确定的参数 → 表单里只读回显(值翻译成中文,用户能一眼核对)
|
||||
Map<String, Object> preset = new LinkedHashMap<>();
|
||||
List<Map<String, String>> recognized = new ArrayList<>();
|
||||
@@ -836,21 +860,37 @@ public class AgentOrchestrator {
|
||||
* 服务端直调必然 302,所以只能把地址交给前端、由前端带用户登录态去取。
|
||||
*/
|
||||
private BrowserToolRequest.BrowserCall buildOptionCall(ToolParam p, CallerContext caller) {
|
||||
if (StringUtils.isBlank(p.getOptionsFrom())) {
|
||||
return buildReadCall(p.getOptionsFrom(), p.getDependsOn(), caller);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成「浏览器代取」的调用描述(下拉字典与「栏目动态字段」共用)。
|
||||
*
|
||||
* <p>差别只在取回的东西怎么用:字典取回的是选项(渲染成下拉),
|
||||
* 栏目字段取回的是**字段定义**(前端就地生成控件)。地址拼装与权限校验完全一致:
|
||||
* 只读工具 + 角色可见 + 依赖字段留 {@code {{占位符}}} 由前端替换。
|
||||
*
|
||||
* @param toolName 只读工具名(如 leave.classStudents / profession.moduleFields)
|
||||
* @param dependsOn 需要留占位符的依赖字段名;为空 = 无参调用
|
||||
* @return 调用描述;工具不存在 / 非只读 / 越权 / 模块未配地址时返回 {@code null}
|
||||
*/
|
||||
private BrowserToolRequest.BrowserCall buildReadCall(String toolName, Collection<String> dependsOn,
|
||||
CallerContext caller) {
|
||||
if (StringUtils.isBlank(toolName)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
ToolDef dict = registry.get(p.getOptionsFrom());
|
||||
ToolDef dict = registry.get(toolName);
|
||||
if (dict == null || !dict.isReadOnly()) {
|
||||
return null;
|
||||
}
|
||||
// 与 fetchDictOptions 同源的角色约束:越权的字典不外泄地址
|
||||
// 与 fetchDictOptions 同源的角色约束:越权的字典/字段定义不外泄地址
|
||||
if (settings.isEnforceRolePermission() && !dict.allowsAny(caller.getRoles())) {
|
||||
return null;
|
||||
}
|
||||
return executor.prepareOptionCall(dict, p.getDependsOn());
|
||||
return executor.prepareOptionCall(dict, dependsOn);
|
||||
} catch (Exception e) {
|
||||
log.warn("生成代取选项描述失败 {}:{}", p.getOptionsFrom(), e.toString());
|
||||
log.warn("生成代取描述失败 {}:{}", toolName, e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user