001/** 002 * Copyright (c) 2025-2026, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.gnu.org/licenses/lgpl-3.0.txt 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package dev.tinyflow.core.node; 017 018 019import dev.tinyflow.core.chain.Chain; 020import dev.tinyflow.core.chain.ChainSuspendException; 021import dev.tinyflow.core.chain.Parameter; 022import dev.tinyflow.core.chain.RefType; 023import dev.tinyflow.core.chain.repository.ChainStateField; 024 025import java.util.*; 026 027public class ConfirmNode extends BaseNode { 028 029 private String message; 030 private List<Parameter> confirms; 031 032 public String getMessage() { 033 return message; 034 } 035 036 public void setMessage(String message) { 037 this.message = message; 038 } 039 040 public List<Parameter> getConfirms() { 041 return confirms; 042 } 043 044 public void setConfirms(List<Parameter> confirms) { 045 if (confirms != null) { 046 for (Parameter confirm : confirms) { 047 confirm.setRefType(RefType.INPUT); 048 confirm.setRequired(true); // 必填,才能正确通过 getParameterValuesOnly 获取参数值 049 confirm.setName(confirm.getName()); 050 } 051 } 052 this.confirms = confirms; 053 } 054 055 056 @Override 057 public Map<String, Object> execute(Chain chain) { 058 059 List<Parameter> confirmParameters = new ArrayList<>(); 060 addConfirmParameter(confirmParameters); 061 062 if (confirms != null) { 063 for (Parameter confirm : confirms) { 064 Parameter clone = confirm.clone(); 065 clone.setName(confirm.getName() + "__" + getId()); 066 clone.setRefType(RefType.INPUT); 067 confirmParameters.add(clone); 068 } 069 } 070 071 Map<String, Object> values; 072 try { 073 values = chain.getState().resolveParameters(this, confirmParameters); 074 // 移除 confirm 参数,方便在其他节点二次确认,或者在 for 循环中第二次获取 075 chain.updateStateSafely(state -> { 076 for (Parameter confirmParameter : confirmParameters) { 077 state.getMemory().remove(confirmParameter.getName()); 078 } 079 return EnumSet.of(ChainStateField.MEMORY); 080 }); 081 } catch (ChainSuspendException e) { 082 chain.updateStateSafely(state -> { 083 state.setMessage(message); 084 return EnumSet.of(ChainStateField.MESSAGE); 085 }); 086 087 if (confirms != null) { 088 List<Parameter> newParameters = new ArrayList<>(); 089 for (Parameter confirm : confirms) { 090 Parameter clone = confirm.clone(); 091 clone.setName(confirm.getName() + "__" + getId()); 092 clone.setRefType(RefType.REF); // 固定为 REF 093 newParameters.add(clone); 094 } 095 096 // 获取参数值,不会触发 ChainSuspendException 错误 097 Map<String, Object> parameterValues = chain.getState().resolveParameters(this, newParameters, null, true); 098 099 // 设置 enums,方便前端给用户进行选择 100 for (Parameter confirmParameter : confirmParameters) { 101 if (confirmParameter.getEnums() == null) { 102 Object enumsObject = parameterValues.get(confirmParameter.getName()); 103 confirmParameter.setEnumsObject(enumsObject); 104 } 105 } 106 } 107 108 throw e; 109 } 110 111 112 Map<String, Object> results = new HashMap<>(values.size()); 113 values.forEach((key, value) -> { 114 int index = key.lastIndexOf("__"); 115 if (index >= 0) { 116 results.put(key.substring(0, index), value); 117 } else { 118 results.put(key, value); 119 } 120 }); 121 122 return results; 123 } 124 125 126 private void addConfirmParameter(List<Parameter> parameters) { 127 // “确认 和 取消” 的参数 128 Parameter parameter = new Parameter(); 129 parameter.setRefType(RefType.INPUT); 130 parameter.setId("confirm"); 131 parameter.setName("confirm__" + getId()); 132 parameter.setRequired(true); 133 134 List<Object> selectionData = new ArrayList<>(); 135 selectionData.add("yes"); 136 selectionData.add("no"); 137 138 parameter.setEnums(selectionData); 139 parameter.setContentType("text"); 140 parameter.setFormType("confirm"); 141 parameters.add(parameter); 142 } 143 144 145}