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

Discord Ask按钮点击无法触发Modal弹窗问题排查求助

问题分析与解决方案

原代码核心问题是没有正确创建并触发Discord Modal窗口,反而用禁用按钮模拟输入流程,完全不符合Modal的使用逻辑,同时混用了新旧Discord.js组件构建器,导致执行错误。以下是修正后的完整代码,实现点击按钮弹出Modal窗口收集用户反馈的功能:

const { SlashCommandBuilder } = require("discord.js");
const { 
  ActionRowBuilder, ButtonStyle, ButtonBuilder, 
  ModalBuilder, TextInputBuilder, TextInputStyle,
  EmbedBuilder 
} = require("discord.js");

module.exports = {
  data: new SlashCommandBuilder()
    .setName("Ask")
    .setDescription("Is there a problem using it? 😥"),
  async execute(interaction) {
    // 创建触发Modal的按钮
    const buttonRow = new ActionRowBuilder()
      .addComponents(
        new ButtonBuilder()
          .setCustomId("open_modal")
          .setLabel("Start Inquiry")
          .setStyle(ButtonStyle.Primary)
      );

    await interaction.reply({
      content: "Please press the button below to start the inquiry.",
      components: [buttonRow],
      ephemeral: true
    });

    // 监听按钮点击
    const buttonCollector = interaction.channel.createMessageComponentCollector({
      componentType: "BUTTON",
      time: 10 * 60 * 1000,
    });

    buttonCollector.on("collect", async (buttonInteraction) => {
      if (buttonInteraction.customId === "open_modal") {
        // 创建Modal窗口
        const inquiryModal = new ModalBuilder()
          .setCustomId("inquiry_modal")
          .setTitle("Submit Your Inquiry");

        // 创建标题输入框
        const titleInput = new TextInputBuilder()
          .setCustomId("inquiry_title")
          .setLabel("Inquiry Title")
          .setStyle(TextInputStyle.Short)
          .setPlaceholder("Enter a brief title for your issue")
          .setRequired(true);

        // 创建内容输入框
        const contentInput = new TextInputBuilder()
          .setCustomId("inquiry_content")
          .setLabel("Inquiry Content")
          .setStyle(TextInputStyle.Paragraph)
          .setPlaceholder("Describe your problem in detail")
          .setRequired(true);

        // 将输入框添加到行中
        const titleRow = new ActionRowBuilder().addComponents(titleInput);
        const contentRow = new ActionRowBuilder().addComponents(contentInput);

        // 向Modal添加行
        inquiryModal.addComponents(titleRow, contentRow);

        // 弹出Modal窗口
        await buttonInteraction.showModal(inquiryModal);

        // 监听Modal提交
        const modalSubmit = await buttonInteraction.awaitModalSubmit({
          time: 10 * 60 * 1000,
          filter: i => i.user.id === interaction.user.id
        }).catch(err => {
          // 处理超时或错误
          buttonCollector.stop("modal_timeout");
          return null;
        });

        if (modalSubmit) {
          // 获取用户输入的内容
          const title = modalSubmit.fields.getTextInputValue("inquiry_title");
          const content = modalSubmit.fields.getTextInputValue("inquiry_content");
          const user = modalSubmit.user;

          // 创建反馈嵌入消息
          const embed = new EmbedBuilder()
            .setTitle(`New Inquiry from ${user.tag}`)
            .addFields(
              { name: "Title", value: title, inline: false },
              { name: "Content", value: content, inline: false }
            )
            .setFooter({ text: `User ID: ${user.id}` })
            .setColor("Green")
            .setThumbnail(user.displayAvatarURL({ dynamic: true }));

          // 发送到指定频道(替换为你的频道ID)
          const channelId = "your_channel_id_here";
          const channel = interaction.guild.channels.cache.get(channelId);
          if (channel) {
            await channel.send({ embeds: [embed] });
          }

          // 回复用户确认
          await modalSubmit.reply({
            content: "Your inquiry has been successfully submitted! We'll get back to you soon 😉",
            ephemeral: true
          });

          buttonCollector.stop("completed");
        }
      }
    });

    buttonCollector.on("end", async (collected, reason) => {
      if (reason === "modal_timeout") {
        await interaction.followUp({
          content: "Your inquiry session has timed out. Please try again later.",
          ephemeral: true
        });
      }
    });
  },
};

关键修改说明

  • 正确创建Modal:使用ModalBuilder构建真正的Modal窗口,搭配TextInputBuilder创建文本输入框,通过showModal()方法弹出。
  • 替换旧组件:统一使用Discord.js v14+的构建器(如ActionRowBuilder而非MessageActionRow),避免版本兼容问题。
  • 简化逻辑:移除多余的按钮收集器,改用awaitModalSubmit()监听Modal提交事件,流程更清晰。
  • 添加输入验证:设置输入框为必填项,并添加占位提示,提升用户体验。
  • 错误处理:处理Modal超时情况,给用户明确反馈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 23:50:58