package jnpf.onlinedev.util;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import jnpf.exception.DataException;
|
import jnpf.model.visualjson.FieLdsModel;
|
import jnpf.onlinedev.model.FormDisplaySchema;
|
import jnpf.util.JsonUtil;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import java.util.*;
|
|
/** Converts published form values through the platform's existing lookup engine. */
|
@Service
|
@RequiredArgsConstructor
|
public class FormDisplayValueService {
|
private final OnlineSwapDataUtils converter;
|
private static final ObjectMapper JSON = new ObjectMapper();
|
|
public Map<String, Object> convert(String formId, String configuration, Map<String, Object> raw) {
|
List<FormDisplaySchema.Field> fields = FormDisplaySchema.parse(configuration);
|
List<FieLdsModel> models = new ArrayList<>();
|
Map<String, List<FieLdsModel>> children = new LinkedHashMap<>();
|
for (FormDisplaySchema.Field field : fields) {
|
if (!field.isSupported()) continue;
|
ObjectNode config = (ObjectNode) field.getConfiguration().deepCopy();
|
config.put("__vModel__", field.getColumn());
|
// Approval-page display values use dates, independent of the form editor format.
|
if (Set.of("datePicker", "dateCalculate", "createTime", "modifyTime").contains(field.getType()))
|
config.put("format", "yyyy-MM-dd");
|
if (field.getType().isEmpty()) ((ObjectNode) config.with("__config__")).put("jnpfKey", "input");
|
FieLdsModel model = JsonUtil.getJsonToBean(config.toString(), FieLdsModel.class);
|
if (field.getTable().isEmpty()) models.add(model);
|
else children.computeIfAbsent(field.getTable(), k -> new ArrayList<>()).add(model);
|
}
|
for (Map.Entry<String, List<FieLdsModel>> table : children.entrySet()) {
|
FieLdsModel model = JsonUtil.getJsonToBean("{\"__vModel__\":\"" + table.getKey()
|
+ "\",\"__config__\":{\"jnpfKey\":\"table\"}}", FieLdsModel.class);
|
model.getConfig().setChildren(table.getValue());
|
models.add(model);
|
}
|
Map<String, Object> data = JsonUtil.stringToMap(JsonUtil.getObjectToString(raw));
|
for (String table : children.keySet()) {
|
Object value = data.get(table);
|
if (value instanceof String) {
|
try { data.put(table, JsonUtil.getJsonToListMap((String) value)); }
|
catch (Exception e) { throw new DataException("子表数据格式错误: " + table); }
|
}
|
}
|
List<Map<String, Object>> rows = new ArrayList<>();
|
rows.add(data);
|
converter.getSwapInfoStrict(rows, models, formId);
|
// Strict lookup validation in OnlineSwapDataUtils rejects missing selected IDs.
|
// Also reject silent fallback/empty results from relation/popup resolvers.
|
JsonNode before = JSON.valueToTree(raw), after = JSON.valueToTree(data);
|
for (FormDisplaySchema.Field field : fields) {
|
if (!field.isSupported() || !field.isReference()) continue;
|
if (field.getTable().isEmpty()) check(field, before.get(field.getColumn()), after.get(field.getColumn()));
|
else {
|
JsonNode oldRows = before.path(field.getTable());
|
if (oldRows.isTextual()) {
|
try { oldRows = JSON.readTree(oldRows.asText()); }
|
catch (Exception e) { throw new DataException("子表数据格式错误: " + field.getTable()); }
|
}
|
for (int i = 0; i < oldRows.size(); i++) check(field, oldRows.path(i).get(field.getColumn()),
|
after.path(field.getTable()).path(i).get(field.getColumn()));
|
}
|
}
|
return data;
|
}
|
private void check(FormDisplaySchema.Field field, JsonNode raw, JsonNode display) {
|
if (raw == null || raw.isNull() || raw.isArray() && raw.isEmpty()
|
|| raw.isTextual() && (raw.asText().isBlank() || "[]".equals(raw.asText()))) return;
|
if (display == null || display.isNull() || !display.isValueNode() || display.asText().isBlank())
|
throw new DataException("无法解析字段显示值: " + field.getLabel() + " (" + field.getPath() + ")");
|
if (Set.of("relationForm", "popupSelect", "popupTableSelect").contains(field.getType()) && display.equals(raw))
|
throw new DataException("关联字段未返回显示文本: " + field.getLabel());
|
}
|
}
|