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
相关产品推荐
相关产品推荐

