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

Discord.js工单系统按钮仅单次可用问题排查求助

问题排查与解决方案

核心问题分析

1. UNLOCK/DELETE按钮失效原因

处理reopen-ticket和delete-ticket按钮的代码未对交互进行回应,Discord要求所有按钮交互必须在3秒内通过deferReply或reply确认,否则会标记交互失败,按钮变为灰色不可用。

2. 二次Confirm后频道无变化原因

  • 缺少错误捕获机制,若频道改名/权限修改操作因权限不足、参数错误等原因失败,代码会静默中断,无法完成后续状态变更。
  • 异步操作顺序不合理:原代码先发送UNLOCK/DELETE消息再执行状态变更,若状态变更失败,会出现“消息已发送但频道未更新”的矛盾情况。

修复后的代码

1. 锁定工单及CONFIRM/CANCEL处理

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isButton() || !interaction.customId.startsWith('close-ticket')) return;

  try {
    // 先回应交互,避免超时
    await interaction.deferReply({ ephemeral: true });
    const type = interaction.customId.split('-')[2] || null;

    if (!type) {
      // 发送确认弹窗
      await interaction.channel.send({
        embeds: [new MessageEmbed().setDescription(client.msg['xacnhan_dongticket'])],
        components: [
          new MessageActionRow().addComponents(
            new MessageButton()
              .setEmoji('✔')
              .setLabel('CONFIRM')
              .setStyle('SECONDARY')
              .setCustomId('close-ticket-confirm'),
            new MessageButton()
              .setEmoji('❌')
              .setLabel('CANCEL')
              .setStyle('SECONDARY')
              .setCustomId('close-ticket-cancel')
          )
        ]
      });
      await interaction.editReply('确认弹窗已发送');
    } else if (type === 'confirm') {
      // 先执行频道状态变更,再发送操作结果消息
      await interaction.channel.setName(`closed-${interaction.channel.name}`);
      await interaction.channel.permissionOverwrites.edit(interaction.channel.topic, {
        VIEW_CHANNEL: false,
        SEND_MESSAGES: false
      });

      // 删除确认弹窗,发送锁定成功消息
      await interaction.message.delete();
      await interaction.channel.send({
        embeds: [new MessageEmbed().setDescription(client.msg['lockticket'])],
        components: [
          new MessageActionRow().addComponents(
            new MessageButton()
              .setEmoji('🔓')
              .setLabel('UNLOCK')
              .setStyle('SECONDARY')
              .setCustomId('reopen-ticket'),
            new MessageButton()
              .setEmoji('🚮')
              .setLabel('DELETE')
              .setStyle('SECONDARY')
              .setCustomId('delete-ticket')
          )
        ]
      });

      await interaction.editReply('工单已锁定');
    } else if (type === 'cancel') {
      // 删除确认弹窗,告知用户操作取消
      await interaction.message.delete();
      await interaction.editReply('已取消锁定操作');
    }

    // 10秒后删除临时回复(提升用户体验)
    setTimeout(() => interaction.deleteReply().catch(() => {}), 10000);
  } catch (error) {
    console.error('处理锁定工单时出错:', error);
    await interaction.editReply('操作失败,请稍后重试').catch(() => {});
  }
});

2. UNLOCK/DELETE按钮处理

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isButton()) return;

  try {
    if (interaction.customId === 'reopen-ticket') {
      await interaction.deferReply({ ephemeral: true });
      // 恢复频道状态
      await interaction.channel.setName(interaction.channel.name.replaceAll('closed-', ''));
      await interaction.channel.permissionOverwrites.edit(interaction.channel.topic, {
        VIEW_CHANNEL: true,
        SEND_MESSAGES: true
      });
      // 删除锁定状态消息
      await interaction.message.delete();
      await interaction.editReply('工单已解锁');
      setTimeout(() => interaction.deleteReply().catch(() => {}), 10000);
    } else if (interaction.customId === 'delete-ticket') {
      await interaction.deferReply({ ephemeral: true });
      // 生成并发送工单记录
      const attachment = await createTranscript(interaction.channel, { fileName: `${interaction.channel.name}.html` });
      const data = await db.findOne({});
      if (data) {
        await interaction.guild.channels.cache.get(data.logId).send({ files: [attachment] });
      }
      // 删除锁定状态消息,延迟删除频道
      await interaction.message.delete();
      await interaction.editReply('工单将在3秒后删除');
      setTimeout(async () => {
        await interaction.channel.delete().catch(err => console.error('删除频道失败:', err));
      }, 3000);
    }
  } catch (error) {
    console.error('处理解锁/删除工单时出错:', error);
    await interaction.editReply('操作失败,请稍后重试').catch(() => {});
  }
});

额外注意事项

  • 确保机器人拥有以下权限:管理频道、管理角色权限、发送消息、嵌入链接,否则状态变更和消息发送会失败。
  • channel.topic存储用户ID的逻辑需确保稳定,若频道topic被意外修改,会导致权限变更失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:05:05