You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Converse.js 注销重连后初始化异常:切换按钮无法唤起聊天控制盒

Converse.js 注销重连后初始化异常:切换按钮无法唤起聊天控制盒

问题分析

你遇到的核心问题是重复调用converse.initialize()导致的内部状态冲突。Converse.js 的初始化方法设计为仅执行一次,重复调用会让它的内部连接实例、DOM 元素绑定、事件监听逻辑出现混乱——这就是为什么注销后重新登录,右上角的切换按钮点击无反应的原因。

从你的代码来看,每次点击切换按钮时都会重新执行useConverse(),而这个函数里又会跑一遍converse.initialize(),相当于每次切换都在创建新的 Converse 实例,旧实例的残留状态和新实例的DOM元素互相干扰,最终导致控制盒无法正常渲染。

解决方案:分离初始化与登录/注销逻辑

我们需要把「全局初始化」和「登录/注销操作」拆分开,初始化只做一次,后续的状态切换完全用 Converse.js 官方提供的 API 来处理。

1. 全局初始化(仅执行一次)

把插件注册、基础配置初始化放在页面加载时执行,不要重复调用:

// 页面加载完成后执行一次全局初始化
document.addEventListener('DOMContentLoaded', function() {
    // 注册自定义插件,仅需一次
    converse.plugins.add('_converse', {
        initialize: function () {
            window.top._converse = this._converse;
            this._converse.api.listen.on('connected', onConnected);
            this._converse.api.listen.on('reconnected', onReconnected);
            this._converse.api.listen.on('disconnected', onDisconnected);
        },
        overrides: {
            handleMessageStanza : async function (stanza) {
                let _broadcast = stanza.getAttribute('broadcast');
                let _priortity = stanza.getAttribute('priority');
                if ( _broadcast ) return;
                this.__super__.handleMessageStanza.apply(this, arguments);
            }
        }
    });

    // 初始化Converse基础配置,不立即登录
    converse.initialize({
        user_group_prefix : window.top.$('#xmppPrefixCreation').val(),
        bosh_service_url: window.top.$('#boshUrl').val(),
        authentication: 'login',
        allow_logout: false,
        debug : true,
        i18n : window.top.$('#xmppLanguage').val(),
        default_domain : window.top.$('#xmppDomain').val(),
        whitelisted_plugins: ['_converse'],
        allow_dragresize : true,
        muc_nickname_from_jid : true,
        allow_contact_removal : false,
        allow_contact_requests : false,
        show_client_info : false,
        allow_non_roster_messaging : true,
        filter_by_resource : true,
        synchronize_availability : true,
        view_mode: 'overlayed',
        assets_path: 'js/conversejs/',
        discover_connection_methods: false,
        auto_login: false, // 关键:禁止自动登录,手动控制登录流程
        show_controlbox_by_default: false // 初始不显示控制盒,登录后再显示
    });
});

2. 独立的登录/注销函数

用 Converse 官方 API 处理登录和注销,不要重新初始化:

// 登录操作
function doStartChat() {
    const xmppJID = window.top.$('#jid').val();
    const xmppPwd = window.top.$('#pass').val();
    const xmppPrefixCreation = window.top.$('#xmppPrefixCreation').val();
    const filteredData = getFilteredData(); // 替换成你获取过滤用户/群组的逻辑

    // 动态更新过滤配置(如果需要每次登录都刷新)
    converse.api.settings.update({
        filtered_users: toJID(filteredData.users),
        filtered_groups: toPrefixGroup(filteredData.groups),
        user_group_prefix: xmppPrefixCreation
    });

    // 执行登录
    converse.api.login(`${xmppJID}/converse`, xmppPwd)
        .then(() => {
            session.setAttribute("ChatLogged", true);
            // 登录成功后主动唤起控制盒
            converse.api.controlbox.show();
        })
        .catch(err => console.error('登录失败:', err));
}

// 注销操作
function doLogoutChat() {
    converse.api.logout()
        .then(() => {
            session.setAttribute("ChatLogged", false);
            // 注销后隐藏控制盒
            converse.api.controlbox.hide();
        })
        .catch(err => console.error('注销失败:', err));
}

// 按钮切换逻辑
function toggleChatSession() {
    if (!session) return;
    const isLoggedChat = Boolean(session.getAttribute("ChatLogged"));
    isLoggedChat ? doLogoutChat() : doStartChat();
}

关键修改点说明

  • 插件仅注册一次:避免重复添加插件导致的事件监听冲突
  • 初始化仅执行一次:设置auto_login: false,把登录控制权交给我们自己的函数
  • 用官方API管理状态converse.api.login()converse.api.logout()是Converse设计用来处理状态切换的方法,内部会正确清理旧连接、重置状态
  • 主动控制控制盒显示:登录成功后调用controlbox.show(),确保控制盒正常渲染;注销后调用hide()清理界面

额外检查项

  1. 打开浏览器控制台的 debug 日志(你已经设置debug: true),查看登录/注销过程中是否有隐藏的错误提示
  2. 确认assets_path配置正确,确保Converse的资源文件(比如语言包)能正常加载
  3. 测试时注意session中ChatLogged的状态是否和实际登录状态同步

这样修改后,你应该就能正常切换登录/注销状态,控制盒也能正常唤起了。

火山引擎 最新活动