You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 03:22:05