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

Vaadin 8 Upload组件addSucceededListener时序问题:如何先弹确认再开文件选择窗

问题根源

你当前的逻辑顺序完全颠倒:addSucceededListener是Vaadin Upload组件的上传成功回调监听器,仅当用户选中文件、上传流程完全执行完成后才会触发,所以你写在这个监听器里的确认弹窗,必然会在选文件之后才弹出。

解决方案

你需要先拦截上传触发动作,完成确认后再唤起文件选择窗口,推荐用「自定义触发按钮+隐藏原生Upload」的方案实现,逻辑清晰且改动量小:

步骤1:修改前端模板

隐藏原生Upload组件,新增一个普通按钮作为上传触发入口:

<!-- 新增自定义触发按钮 -->
<vaadin-button caption="Incarc INDICATORI" _id="customUploadBtn" :right></vaadin-button>
<!-- 原生Upload加hidden隐藏,仅做文件接收能力 -->
<vaadin-upload button-caption="Incarc INDICATORI " _id="cmdIncarcRaportInd" :right hidden></vaadin-upload>

步骤2:后端绑定自定义按钮的点击逻辑

把前置校验、确认弹窗逻辑移到自定义按钮的点击事件中,用户确认后用JS主动唤起隐藏的Upload的文件选择窗口:

// 给原生Upload设置固定ID,方便JS定位
getCmdIncarcRaportInd().setId("upload-indicatori");

// 自定义按钮点击逻辑
getCustomUploadBtn().addClickListener(event -> {
    int NR_Raport = 0;
    String WBL = getCheBL().getValue() ? "B" : "I";
    if(raport != null) NR_Raport = Numeric.getValInt(raport.get("Nr. Raport"));
    
    // 前置校验报告编号
    if (NR_Raport == 0) {
        Notification notif = new Notification("Atentie",
                "NR Raport incorect",
                Notification.Type.ERROR_MESSAGE);
        notif.setDelayMsec(-1);
        notif.show(Page.getCurrent());
        return;
    }

    // 判断是否需要弹Base Line确认框
    if(WBL.equals("B")) {
        ConfirmButton cd = new ConfirmButton("Confirmare");
        cd.misWinTitle = "Atentie MIS";
        cd.misWinText = "Incarcati valori Base Line ? Daca exista deja, cele vechi se vor rescrie cu valorile noi. CONFIRMATI BASE LINE (DA / NU) ?";
        cd.misButOK = "DA";
        cd.misButCancel = "NU";
        cd.setOkAction(() -> {
            // 确认后主动触发文件选择窗口
            Page.getCurrent().getJavaScript().execute("document.getElementById('upload-indicatori').querySelector('input[type=file]').click();");
        });
        cd.setCancelAction(() -> {});
        cd.openInModalPopup();
    } else {
        // 无需确认直接触发文件选择
        Page.getCurrent().getJavaScript().execute("document.getElementById('upload-indicatori').querySelector('input[type=file]').click();");
    }
});

步骤3:简化原有SucceededListener逻辑

移除原来监听器里的前置校验、确认弹窗逻辑,仅保留上传完成后的业务处理代码即可:

getCmdIncarcRaportInd().addSucceededListener(event -> {
    String WBL = getCheBL().getValue() ? "B" : "I";
    int NR_Raport = 0;
    if(raport != null) NR_Raport = Numeric.getValInt(raport.get("Nr. Raport"));
    int NR_RaportW = WBL.equals("B") ? 99 : NR_Raport;
    String raspuns = "ok";

    // 校验文件名
    if(!receiver.getFile().getName().split("_")[0].equals(proiect.get("Prj cod"))) {
        Notification notif = new Notification("Atentie", "Cod Proiect Incorect",
                Notification.Type.ERROR_MESSAGE);
        notif.setDelayMsec(-1);
        notif.show(Page.getCurrent());
        return;
    }

    // 执行业务逻辑
    try {
        if(WBL.equals("B")) {
            raspuns = Utility.getSomeData(receiver.getFile(), proiect, 99, themeDisplay);
        } else {
            raspuns = Utility.DoSomeStuff(receiver.getFile(), proiect, NR_RaportW, themeDisplay);
        }
    } catch (IOException | SQLException e) {
        raspuns = e.getMessage();
    }

    // 结果通知+刷新表格
    String notifyTitle = WBL.equals("B") ? "Atentie - Incarcare Base Line Indicatori" : "Atentie - Incarcare Rap Indicatori";
    Notification notificare = new Notification(notifyTitle,
            raspuns,
            Notification.Type.ERROR_MESSAGE);
    notificare.setDelayMsec(-1);
    notificare.show(Page.getCurrent());
    incarcGrdIndicatori(prj_cod);
    receiver.uploadFinished(event);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:15:04