Button mapping attirbute className not support [list]

本文介绍了一种ConfigException异常的处理方法,通过设置multiMapping为true来解决按钮映射属性类名不支持列表的问题,并展示了具体的配置文件修改示例。

 

Caused by: com.vtradex.thorn.server.exception.ConfigException: Button mapping attirbute className not support [list]
	at com.vtradex.thorn.server.action.DealParamAction.getMappingValue(DealParamAction.java:502)
	at com.vtradex.thorn.server.action.DealParamAction.convertMappingValue(DealParamAction.java:486)
	at com.vtradex.thorn.server.action.DealParamAction.execute(DealParamAction.java:73)
	... 28 more

 处理:将multiMapping值设为true

 

 

<tableCommit id="bcWeekInit" title="bcWeekInit" process="bcWeekProcess.checkWeekPlanMerge" enableType="multi" multiMapping="true" download="false" closeTransactional="true" confirmMessage="confirm">
                <enableExpression><![CDATA[lot.status={'OPEN'}]]></enableExpression>
                <mappings>
                    <mapping id="objs" className="list">
                        <entries/>
                    </mapping>
                </mappings>
                <actions>
                    <action managerName="noTransactionManager" methodName="bcWeekInit" parameter="objs"/>
                </actions>
                <forwards/>
            </tableCommit>

 -----mappingConfig.xml

 

	<element pageId="maintainBcWeekLotsPage" buttonId="bcWeekInit">
		<mapping id="objs" className="list" />
	</element>

 

ERROR com.altair.common.config.ExceptionControllerAdvice:73 - Parameter exceptions: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public reactor.core.publisher.Flux<com.altair.userserver.entity.StreamResponse> com.altair.userserver.controller.AIDify.DifyController.test2(com.altair.userserver.vo.MessageVO) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:161) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:131) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)报错信息 package com.altair.userserver.controller.AIDify; import com.altair.userserver.entity.BlockResponse; import com.altair.userserver.entity.StreamResponse; import com.altair.userserver.service.impl.DifyService; import com.altair.userserver.vo.MessageVO; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; @RestController @RequestMapping(“/api”) @RequiredArgsConstructor public class DifyController { @Value("${dify.api.key}") private String testKey; private final DifyService difyService; @PostMapping ("/stream") public Flux<StreamResponse> test2(@RequestBody MessageVO vo) { return difyService.streamingMessage(vo.getQuery(),0L, testKey); } }控制层代码 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>智能助手</title> <style> :root { --primary-color: #4f46e5; --assistant-bg: #f3f4f6; --user-bg: #dbeafe; } * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f9fafb; min-height: 100vh; } /* 悬浮助手按钮 */ .floating-assistant { position: fixed; bottom: 30px; right: 30px; width: 60px; height: 60px; border-radius: 50%; background-color: var(--primary-color); color: white; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); z-index: 1000; transition: transform 0.3s ease; } .floating-assistant:hover { transform: scale(1.05); } .assistant-icon { font-size: 24px; font-weight: bold; } /* 聊天对话框 */ .chat-container { position: fixed; bottom: 100px; right: 30px; width: 400px; height: 500px; background: white; border-radius: 12px; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; overflow: hidden; z-index: 999; opacity: 0; transform: translateY(20px); transition: all 0.3s ease; } .chat-container.active { opacity: 1; transform: translateY(0); } .chat-header { background-color: var(--primary-color); color: white; padding: 15px; font-weight: 600; display: flex; justify-content: space-between; align-items: center; } .close-btn { background: none; border: none; color: white; cursor: pointer; font-size: 18px; } .chat-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; } .message { max-width: 85%; padding: 12px 16px; border-radius: 18px; line-height: 1.5; animation: fadeIn 0.3s ease; } .assistant-message { background-color: var(--assistant-bg); align-self: flex-start; border-bottom-left-radius: 4px; } .user-message { background-color: var(--user-bg); align-self: flex-end; border-bottom-right-radius: 4px; } .chat-input-area { padding: 15px; border-top: 1px solid #e5e7eb; display: flex; gap: 10px; } .message-input { flex: 1; padding: 12px 15px; border: 1px solid #d1d5db; border-radius: 24px; outline: none; font-size: 14px; } .send-btn { background-color: var(--primary-color); color: white; border: none; width: 40px; height: 40px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; } .typing-indicator { display: inline-flex; align-items: center; padding: 8px 12px; background: var(--assistant-bg); border-radius: 18px; } .typing-dot { width: 8px; height: 8px; background-color: #9ca3af; border-radius: 50%; margin: 0 2px; animation: typing 1.4s infinite ease-in-out; } .typing-dot:nth-child(1) { animation-delay: 0s; } .typing-dot:nth-child(2) { animation-delay: 0.2s; } .typing-dot:nth-child(3) { animation-delay: 0.4s; } @keyframes typing { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-5px); } } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } </style> </head> <body> <!-- 悬浮助手按钮 --> <div class="floating-assistant" id="assistantBtn"> <div class="assistant-icon">AI</div> </div> <!-- 聊天对话框 --> <div class="chat-container" id="chatContainer"> <div class="chat-header"> <span>智能助手</span> <button class="close-btn" id="closeBtn">×</button> </div> <div class="chat-messages" id="chatMessages"> <!-- 消息将通过JS动态添加 --> </div> <div class="chat-input-area"> <input type="text" class="message-input" id="messageInput" placeholder="输入您的问题..." autocomplete="off" > <button class="send-btn" id="sendBtn"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z"/> </svg> </button> </div> </div> <script> // DOM元素 const assistantBtn = document.getElementById('assistantBtn'); const chatContainer = document.getElementById('chatContainer'); const closeBtn = document.getElementById('closeBtn'); const chatMessages = document.getElementById('chatMessages'); const messageInput = document.getElementById('messageInput'); const sendBtn = document.getElementById('sendBtn'); // 当前流式响应的EventSource let eventSource = null; // 当前正在处理的响应消息元素 let currentResponseElement = null; // 初始化事件监听 assistantBtn.addEventListener('click', toggleChat); closeBtn.addEventListener('click', closeChat); sendBtn.addEventListener('click', sendMessage); messageInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { sendMessage(); } }); // 切换聊天对话框 function toggleChat() { chatContainer.classList.toggle('active'); if (chatContainer.classList.contains('active')) { messageInput.focus(); } } // 关闭聊天对话框 function closeChat() { chatContainer.classList.remove('active'); // 关闭任何打开的SSE连接 if (eventSource) { eventSource.close(); eventSource = null; } } // 发送消息 function sendMessage() { const message = messageInput.value.trim(); if (!message) return; // 添加用户消息 addMessage(message, 'user'); messageInput.value = ''; // 添加等待中的助手消息(占位) currentResponseElement = createTypingIndicator(); chatMessages.appendChild(currentResponseElement); chatMessages.scrollTop = chatMessages.scrollHeight; // 调用API获取流式响应 fetchStreamingResponse(message); } // 创建输入中指示器 function createTypingIndicator() { const typingElement = document.createElement('div'); typingElement.className = 'message assistant-message typing-indicator'; typingElement.innerHTML = ` <div class="typing-dot"></div> <div class="typing-dot"></div> <div class="typing-dot"></div> `; return typingElement; } // 调用流式API function fetchStreamingResponse(query) { // 关闭之前的连接(如果有) if (eventSource) eventSource.close(); // 创建API URL(根据实际部署修改) const apiUrl = 'http://localhost:8089/api/stream'; // 使用Fetch API + ReadableStream处理流式响应 fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', // 在实际应用中应添加认证头 }, body: JSON.stringify({ query }) }) .then(response => { const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; // 替换输入指示器为真实消息容器 const messageElement = document.createElement('div'); messageElement.className = 'message assistant-message'; chatMessages.replaceChild(messageElement, currentResponseElement); currentResponseElement = messageElement; // 处理流数据 const processStream = ({ done, value }) => { if (done) { console.log('流结束'); return; } buffer += decoder.decode(value, { stream: true }); // 处理完整的JSON行 const lines = buffer.split('\n'); buffer = lines.pop(); // 保存不完整的行 for (const line of lines) { if (line.trim() === '') continue; try { const eventData = JSON.parse(line); // 只处理包含实际内容的消息事件 if (eventData.event === 'message' && eventData.answer !== null) { currentResponseElement.textContent += eventData.answer; chatMessages.scrollTop = chatMessages.scrollHeight; } } catch (e) { console.error('解析JSON错误:', e); } } // 继续读取 return reader.read().then(processStream); }; return reader.read().then(processStream); }) .catch(error => { console.error('请求错误:', error); currentResponseElement.textContent = '抱歉,请求助手时出错: ' + error.message; chatMessages.scrollTop = chatMessages.scrollHeight; }); } // 添加消息到对话框 function addMessage(text, sender) { const messageElement = document.createElement('div'); messageElement.className = `message ${sender}-message`; messageElement.textContent = text; chatMessages.appendChild(messageElement); chatMessages.scrollTop = chatMessages.scrollHeight; } // 初始示例消息 window.addEventListener('DOMContentLoaded', () => { addMessage('您好!我是智能助手,请问有什么可以帮您?', 'assistant'); }); </script> </body> </html> 前端代码 帮我修改 vo代码如下 package com.altair.userserver.vo; import lombok.Data; @Data public class MessageVO { private String query; }
最新发布
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值