如何用Turbo为GPT-4聊天功能添加输入指示器/骨架加载器?
实现Turbo异步任务期间的加载指示器
步骤1:表单提交时立即显示加载器
修改聊天表单,绑定提交事件到Stimulus控制器的showLoader和resetForm方法,确保用户提交消息后立刻触发加载状态:
<!-- 修改 lessons/sections/messages/_form.html.erb --> <%= form_with(model: message, url: section_messages_path(@section), data: { action: "submit->chat#showLoader chat#resetForm", chat_target: "form" }) do |form| %> <%= form.text_area :content, class: "w-full p-2 border rounded-md", placeholder: "输入消息..." %> <div class="mt-2 flex justify-end"> <%= form.submit "发送", class: "bg-blue-950 text-white px-4 py-2 rounded-md" %> </div> <% end %>
步骤2:异步任务完成后隐藏加载器
在CompletionJob中,当GPT-4响应生成并追加助手消息后,通过Turbo Streams广播调用Stimulus控制器的hideLoader方法:
# 修改 app/jobs/completion_job.rb class CompletionJob < ApplicationJob queue_as :default def perform(chat, message) client = OpenAI::Client.new(access_token: Rails.application.credentials[Rails.env.to_sym][:openai][:api_key]) response = client.chat( parameters: { model: "gpt-4", messages: [{role: "system", content: "lorem ipsum" }, { role: "user", content: message.content}], temperature: 0.7, }) completion = chat.messages.create(content: response.dig("choices", 0, "message", "content"), sender: 'assistant') # 追加助手消息 Turbo::StreamsChannel.broadcast_append_to(chat, target: "messages", partial: "lessons/sections/messages/message", locals: { message: completion }) # 调用Stimulus方法隐藏加载器 Turbo::StreamsChannel.broadcast_action_to( chat, action: :invoke, target: "chat", method: :hideLoader ) end end
步骤3:处理表单提交失败的情况
如果用户消息保存失败,在控制器的错误分支中通过Turbo Stream触发加载器隐藏:
# 修改 controllers/lessons/sections/messages_controller.rb def create @chat = Chat.find_or_create_by(section_id: @section.id, user_id: current_user.id) @message = @chat.messages.build(content: message_params[:content], sender: 'user') if @message.save respond_to do |format| format.turbo_stream { render turbo_stream: turbo_stream.append("messages", partial: "lessons/sections/messages/message", locals: { message: @message }) } end CompletionJob.perform_later(@chat, @message) else @messages = @chat.messages.order(created_at: :asc) @new_message = Message.new respond_to do |format| format.html { render "sections/show" } format.turbo_stream { render turbo_stream: turbo_stream.invoke("chat", "hideLoader") } end end end
验证Stimulus控制器配置
确保Stimulus控制器中已正确声明form目标:
// 保持原Stimulus控制器不变,确认包含以下内容 export default class extends Controller { static targets = ["widget", "container", "form", "loader"]; // ... 其他方法 }
内容的提问来源于stack exchange,提问作者Darksi
相关产品推荐
相关产品推荐

