package jnpf.flowable.util; import com.alibaba.fastjson.JSON; import jnpf.base.ActionResult; import jnpf.base.entity.DictionaryDataEntity; import jnpf.base.model.datainterface.DataInterfacePage; import jnpf.base.model.datainterface.DataInterfaceModel; import jnpf.permission.entity.OrganizeEntity; import jnpf.permission.entity.PositionEntity; import jnpf.permission.entity.RoleEntity; import jnpf.permission.entity.GroupEntity; import jnpf.permission.entity.UserEntity; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** Resolves form component keys before they are written into flow titles. */ @Component @RequiredArgsConstructor public class FlowAuditTitleValueResolver implements FlowAuditTitleUtil.ValueResolver { private final ServiceUtil serviceUtil; @Override public String resolve(Map field, Map config, Object value, Map row) { String raw = FlowAuditTitleUtil.display(value); if (raw == null) { return null; } String key = string(config.get("jnpfKey")); List ids = values(value); switch (key) { case "userSelect": case "createUser": case "modifyUser": return names(ids, serviceUtil.getUserName(ids).stream() .collect(Collectors.toMap(UserEntity::getId, UserEntity::getRealName, (a, b) -> a))); case "customUserSelect": return customUserNames(ids); case "comSelect": case "depSelect": case "currDept": case "currOrganize": return names(ids, serviceUtil.getOrganizeList(ids).stream() .collect(Collectors.toMap(OrganizeEntity::getId, OrganizeEntity::getFullName, (a, b) -> a))); case "posSelect": case "currPosition": return names(ids, serviceUtil.getPosList(ids).stream() .collect(Collectors.toMap(PositionEntity::getId, PositionEntity::getFullName, (a, b) -> a))); case "roleSelect": return names(ids, serviceUtil.getRoleList(ids).stream() .collect(Collectors.toMap(RoleEntity::getId, RoleEntity::getFullName, (a, b) -> a))); case "groupSelect": return names(ids, serviceUtil.getGroupList(ids).stream() .collect(Collectors.toMap(GroupEntity::getId, GroupEntity::getFullName, (a, b) -> a))); case "select": case "treeSelect": case "radio": case "checkbox": case "cascader": return optionNames(field, config, ids, row); case "popupSelect": case "popupTableSelect": return popupNames(field, config, ids, row); case "date": case "dateCalculate": case "createTime": case "modifyTime": return date(field, value, raw); default: return raw; } } private String customUserNames(List ids) { List names = new ArrayList<>(); for (String value : ids) { int separator = value.lastIndexOf("--"); String id = separator < 0 ? value : value.substring(0, separator); String type = separator < 0 ? "user" : value.substring(separator + 2); String name; switch (type) { case "company": case "department": name = names(Collections.singletonList(id), serviceUtil.getOrganizeList(Collections.singletonList(id)) .stream().collect(Collectors.toMap(OrganizeEntity::getId, OrganizeEntity::getFullName))); break; case "position": name = names(Collections.singletonList(id), serviceUtil.getPosList(Collections.singletonList(id)) .stream().collect(Collectors.toMap(PositionEntity::getId, PositionEntity::getFullName))); break; case "role": name = names(Collections.singletonList(id), serviceUtil.getRoleList(Collections.singletonList(id)) .stream().collect(Collectors.toMap(RoleEntity::getId, RoleEntity::getFullName))); break; case "group": name = names(Collections.singletonList(id), serviceUtil.getGroupList(Collections.singletonList(id)) .stream().collect(Collectors.toMap(GroupEntity::getId, GroupEntity::getFullName))); break; default: name = names(Collections.singletonList(id), serviceUtil.getUserName(Collections.singletonList(id)) .stream().collect(Collectors.toMap(UserEntity::getId, UserEntity::getRealName))); } if (name != null) { names.add(name); } } return names.isEmpty() ? null : String.join(",", names); } private String optionNames(Map field, Map config, List ids, Map row) { String type = string(config.get("dataType")); List> options; if ("dictionary".equals(type)) { List dictionary = serviceUtil.getDictionaryData(string(config.get("dictionaryType"))); Map labels = new LinkedHashMap<>(); for (DictionaryDataEntity item : dictionary) { labels.put(item.getId(), item.getFullName()); labels.put(item.getEnCode(), item.getFullName()); } return names(ids, labels); } if ("dynamic".equals(type)) { ActionResult result = serviceUtil.infoToId(string(config.get("propsUrl")), parameters(config, row)); options = result != null && result.getData() instanceof List ? maps((List) result.getData()) : Collections.emptyList(); } else { options = maps(list(field.get("options"))); } Map props = map(field.get("props")); String valueKey = string(props.getOrDefault("value", "id")); String labelKey = string(props.getOrDefault("label", "fullName")); Map labels = new LinkedHashMap<>(); collectOptions(options, valueKey, labelKey, string(props.get("children")), labels); return names(ids, labels); } private String popupNames(Map field, Map config, List ids, Map row) { String interfaceId = string(field.get("interfaceId")); if (interfaceId.isEmpty()) { return null; } DataInterfacePage page = new DataInterfacePage(); page.setIds(ids); page.setPropsValue(string(field.get("propsValue"))); page.setRelationField(string(field.get("relationField"))); List params = new ArrayList<>(); for (Object item : list(config.get("templateJson"))) { Map parameter = map(item); DataInterfaceModel model = JSON.parseObject(JSON.toJSONString(parameter), DataInterfaceModel.class); model.setDefaultValue(parameterValue(parameter, row)); params.add(model); } page.setParamList(params); List> records = serviceUtil.getInterfaceRows(interfaceId, page); Map labels = new LinkedHashMap<>(); for (Map record : records) { Object id = record.get(page.getPropsValue()); Object label = record.get(page.getRelationField()); if (id != null && label != null) { labels.put(String.valueOf(id), String.valueOf(label)); } } return names(ids, labels); } private static Map parameters(Map config, Map row) { Map result = new LinkedHashMap<>(); for (Object item : list(config.get("templateJson"))) { Map parameter = map(item); String field = string(parameter.get("field")); if (!field.isEmpty()) { result.put(field, parameterValue(parameter, row)); } } return result; } private static String parameterValue(Map parameter, Map row) { Object source = parameter.get("sourceType"); if (source != null && !"1".equals(String.valueOf(source))) { return string(parameter.get("defaultValue")); } return string(row.get(string(parameter.get("relationField")))); } private static String date(Map field, Object value, String fallback) { if (!(value instanceof Number) && !fallback.matches("\\d{10,13}")) { return fallback; } try { long timestamp = Long.parseLong(fallback); if (fallback.length() == 10) { timestamp *= 1000; } String format = string(field.get("format")); if (format.isEmpty()) { format = "yyyy-MM-dd HH:mm:ss"; } LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()); return date.format(DateTimeFormatter.ofPattern(format)); } catch (RuntimeException ignored) { return fallback; } } private static void collectOptions(List> options, String valueKey, String labelKey, String childrenKey, Map labels) { for (Map option : options) { Object value = option.get(valueKey); Object label = option.get(labelKey); if (value != null && label != null) { labels.put(String.valueOf(value), String.valueOf(label)); } if (!childrenKey.isEmpty()) { collectOptions(maps(list(option.get(childrenKey))), valueKey, labelKey, childrenKey, labels); } } } private static String names(List ids, Map labels) { List names = new ArrayList<>(); for (String id : ids) { String name = labels.get(id); if (name != null && !name.trim().isEmpty()) { names.add(name); } } return names.isEmpty() ? null : String.join(",", names); } private static List values(Object value) { List list = value instanceof List ? (List) value : list(value); if (list.isEmpty() && value != null) { list = Collections.singletonList(value); } List result = new ArrayList<>(); for (Object item : list) { if (item != null && !(item instanceof Map) && !String.valueOf(item).trim().isEmpty()) { result.add(String.valueOf(item).trim()); } } return result; } private static List list(Object value) { if (value instanceof List) { return (List) value; } if (value instanceof String && ((String) value).trim().startsWith("[")) { try { return JSON.parseArray((String) value); } catch (RuntimeException ignored) { return Collections.emptyList(); } } return Collections.emptyList(); } @SuppressWarnings("unchecked") private static Map map(Object value) { return value instanceof Map ? (Map) value : Collections.emptyMap(); } private static List> maps(List values) { List> result = new ArrayList<>(); for (Object value : values) { if (value instanceof Map) { result.add(map(value)); } } return result; } private static String string(Object value) { return value == null ? "" : String.valueOf(value); } }