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

Shiny应用实时功能与取消按钮实现及切换清空问题求助

修复Shiny应用的模式切换与取消功能问题

核心问题梳理

  • 切换手动/实时模式时,结果表格未自动清空
  • 取消查询按钮无实际功能,无法终止手动查询或停止实时刷新
  • 实时模式下定时器重复创建,导致刷新频率异常
  • 实时模式取消后未同步关闭刷新开关

修复后的完整代码

library(shiny)
library(shinyjs)
library(shinyWidgets)
library(lubridate)

ui <- fluidPage(
  useShinyjs(),
  sidebarPanel(
    selectInput("fecha", "Fecha", choices = c("Manual", "Tiempo Real")),
    
    conditionalPanel("input.fecha == 'Manual'",
                     airDatepickerInput("ini_manual", label = "Fecha Inicio", value = Sys.time() - 3 * (60 * 60), 
                                        addon = 'none',  timepicker = TRUE,  firstDay = 1,
                                        width = "200px", autoClose = TRUE,  timepickerOpts = timepickerOptions(timeFormat = "hh:ii")),
                     airDatepickerInput("fin_manual", label = "Fecha Fin", value = Sys.time(), 
                                        addon = 'none', timepicker = TRUE, firstDay = 1, 
                                        width = "200px", autoClose = TRUE, maxDate = NULL,  timepickerOpts = timepickerOptions(timeFormat = "hh:ii"))
    ),
    
    conditionalPanel("input.fecha == 'Tiempo Real'",
                     materialSwitch(inputId = "refresh", label = "Tiempo Real", value = TRUE, status = "success")
    ),
    actionButton("btnConsulta", "Lanzar Consulta"),
    actionButton("btnCancelarConsulta", "Cancelar Consulta")
  ),
  
  mainPanel(
    tableOutput("tablaResultado")
  )
)

server <- function(input, output, session) {
  # 用reactiveVal存储查询结果,方便清空和更新
  consulta_resultado <- reactiveVal(data.frame())
  
  # 模式切换时清空结果、停止定时器
  observeEvent(input$fecha, {
    consulta_resultado(data.frame())
    shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);')
    if (input$fecha == "Tiempo Real") {
      updateMaterialSwitch(session, "refresh", value = FALSE)
    }
  })
  
  # 手动模式查询逻辑
  observeEvent(input$btnConsulta, {
    if (input$fecha == "Manual") {
      fecha_ini <- input$ini_manual
      fecha_fin <- input$fin_manual
      
      resultado <- data.frame(
        fecha = as.character(seq.POSIXt(from = fecha_ini, to = fecha_fin, by = "hour")),
        Valor = rnorm(length(seq.POSIXt(from = fecha_ini, to = fecha_fin, by = "hour")))
      )
      consulta_resultado(resultado)
    }
  })
  
  # 实时模式定时器管理
  observe({
    if (input$fecha == "Tiempo Real" && input$refresh) {
      # 先清除已有定时器,避免重复创建
      shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);')
      shinyjs::runjs(
        'consultaInterval = setInterval(function() { 
          Shiny.setInputValue("real_time_trigger", Math.random(), {priority: "event"}); 
        }, 5000);'
      )
    } else {
      shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);')
    }
  })
  
  # 实时模式查询触发
  observeEvent(input$real_time_trigger, {
    if (input$fecha == "Tiempo Real" && input$refresh) {
      consulta_tiempo_real <- data.frame(
        fecha = as.character(seq.POSIXt(from = Sys.time(), by = "hour", length.out = 5)),
        Valor = rnorm(5)
      )
      consulta_resultado(consulta_tiempo_real)
    }
  })
  
  # 点击Lanzar Consulta启动实时模式
  observeEvent(input$btnConsulta, {
    if (input$fecha == "Tiempo Real") {
      updateMaterialSwitch(session, "refresh", value = TRUE)
    }
  })
  
  # 取消查询按钮逻辑
  observeEvent(input$btnCancelarConsulta, {
    consulta_resultado(data.frame())
    shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);')
    if (input$fecha == "Tiempo Real") {
      updateMaterialSwitch(session, "refresh", value = FALSE)
    }
  })
  
  # 渲染结果表格
  output$tablaResultado <- renderTable({
    consulta_resultado()
  })
}

shinyApp(ui, server)

关键修改说明

  1. 模式切换处理:新增observeEvent监听模式切换,立即清空表格、停止定时器,实时模式下自动关闭刷新开关
  2. 取消按钮功能:绑定取消按钮逻辑,清空结果、停止定时器,同步关闭实时开关
  3. 定时器优化:创建定时器前先清除已有实例,避免重复创建导致刷新频率异常
  4. 结果存储优化:用reactiveVal存储查询结果,替代原eventReactive,更灵活控制清空和更新
  5. 实时触发分离:新增独立的real_time_trigger输入触发实时查询,避免和手动查询的按钮事件冲突

内容的提问来源于stack exchange,提问作者Raq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:43:19