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

如何为discord.js音乐bot的队列embed功能实现分页效果

注意:如果你使用的是discord.js v13及以上版本,请确保client初始化时已开启GUILD_MESSAGE_COMPONENTS意图,否则按钮交互无法正常触发。

实现步骤

1. 拆分队列生成分页Embed

我们将待播放队列按每页9条拆分,每一页顶部固定保留当前播放歌曲信息,避免翻页后看不到正在播放的内容。

2. 添加分页交互按钮

添加「上一页」「下一页」两个按钮,绑定自定义ID用于识别点击事件。

3. 配置交互收集器

仅允许触发队列命令的用户操作按钮,超时后自动禁用按钮防止无效操作。

完整可运行代码
const Discord = require('discord.js');

module.exports = {
    name: "queue",
    aliases: ['q'],
    description: "查看当前播放队列",
    run: async (client, message, args) => {
        const queue = client.distube.getQueue(message)
        // 队列为空的情况
        if (!queue) return message.channel.send(new Discord.MessageEmbed()
        .setTitle(`**${message.guild.name}的播放队列**`)
        .setDescription(`__正在播放:__\n当前无播放内容`)
        .setColor('RANDOM')
        );

        // 每页展示的待播放歌曲数量
        const songsPerPage = 9;
        // 待播放队列(排除正在播放的第0首)
        const upNextSongs = queue.songs.slice(1);
        // 计算总页数
        const totalPages = Math.ceil(upNextSongs.length / songsPerPage) || 1;
        // 当前页默认设为第1页
        let currentPage = 1;

        // 生成分页Embed的方法
        const generateQueueEmbed = (page) => {
            // 计算当前页展示的歌曲起始和结束索引
            const start = (page - 1) * songsPerPage;
            const end = start + songsPerPage;
            const currentPageSongs = upNextSongs.slice(start, end);

            // 拼接内容,顶部固定展示正在播放的歌曲
            let content = `__正在播放:__\n [${queue.songs[0].name}](${queue.songs[0].url})\n \`${queue.songs[0].formattedDuration} 点歌人: ${queue.songs[0].user.tag}\``;
            
            // 有待播放歌曲的情况拼接列表
            if (currentPageSongs.length > 0) {
                content += `\n__即将播放:__\n ${currentPageSongs.map((song, index) => `\`${start + index + 1}.\` [${song.name}](${song.url})\n \`${song.formattedDuration} 点歌人: ${song.user.tag}\``).join("\n")}`;
            } else {
                content += `\n__即将播放:__\n暂无更多待播放歌曲`;
            }

            // 返回当前页Embed
            return new Discord.MessageEmbed()
                .setTitle(`**${message.guild.name}的播放队列**`)
                .setDescription(content)
                .setColor('RANDOM')
                .setFooter(`第 ${page} / ${totalPages} 页 | 共 ${queue.songs.length} 首歌 | 总时长 ${queue.formattedDuration}`)
        }

        // 生成按钮组件
        const row = new Discord.MessageActionRow()
            .addComponents(
                new Discord.MessageButton()
                    .setCustomId('prev_page')
                    .setLabel('上一页')
                    .setStyle('PRIMARY'),
                new Discord.MessageButton()
                    .setCustomId('next_page')
                    .setLabel('下一页')
                    .setStyle('PRIMARY')
            );

        // 发送初始队列Embed+按钮
        const queueMessage = await message.channel.send({
            embeds: [generateQueueEmbed(currentPage)],
            components: totalPages > 1 ? [row] : [] // 只有1页的话不展示按钮
        });

        // 只有1页不需要做后续交互处理
        if (totalPages <= 1) return;

        // 创建按钮交互收集器,仅响应命令触发者,超时时间设为60秒
        const collector = queueMessage.createMessageComponentCollector({
            filter: i => i.user.id === message.author.id,
            time: 60000
        });

        // 监听按钮点击
        collector.on('collect', async i => {
            // 根据按钮ID切换页面
            if (i.customId === 'prev_page') {
                currentPage = currentPage === 1 ? totalPages : currentPage - 1;
            } else if (i.customId === 'next_page') {
                currentPage = currentPage === totalPages ? 1 : currentPage + 1;
            }

            // 更新Embed
            await i.update({
                embeds: [generateQueueEmbed(currentPage)]
            });
        });

        // 收集器超时后禁用按钮
        collector.on('end', () => {
            const disabledRow = new Discord.MessageActionRow()
                .addComponents(
                    new Discord.MessageButton()
                        .setCustomId('prev_page')
                        .setLabel('上一页')
                        .setStyle('PRIMARY')
                        .setDisabled(true),
                    new Discord.MessageButton()
                        .setCustomId('next_page')
                        .setLabel('下一页')
                        .setStyle('PRIMARY')
                        .setDisabled(true)
                );
            queueMessage.edit({ components: [disabledRow] }).catch(() => {});
        });
    }
}
可自定义配置项
  • 修改songsPerPage的数值可以调整每页展示的待播放歌曲数量
  • 修改time参数可以调整按钮的有效操作时长,单位为毫秒
  • 可自行添加跳转到首页/尾页、跳转到指定页的按钮扩展功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:39:05