跳转到内容
打开/关闭菜单
  • 1 条目
  • 1 用户
  • 147 编辑
Anachronism
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Common.js:修订间差异

MediaWiki界面页面
Ancimen​(留言 | 贡献)
清空全部内容
Ancimen​(留言 | 贡献)
无编辑摘要
 
(未显示同一用户的13个中间版本)
第1行: 第1行:
/* ===== 侧边工具栏 Rail 管理器 ===== */
/* ===== 侧边工具栏 Rail 管理器 ===== */
window.Rail = (function () {
    var items = [];
    var activeId = null;
    var panelEl, overlayEl, buttonsEl, contentEl, titleEl;


    function ensureDOM() {
        if (document.getElementById('rail-container')) return;
        buttonsEl = document.createElement('div');
        buttonsEl.id = 'rail-container';
        buttonsEl.className = 'rail-container';
        overlayEl = document.createElement('div');
        overlayEl.id = 'rail-overlay';
        overlayEl.className = 'rail-overlay';
        panelEl = document.createElement('aside');
        panelEl.id = 'rail-panel';
        panelEl.className = 'rail-panel';
        panelEl.innerHTML = [
            '<div class="rail-panel__header">',
            '  <span class="rail-panel__title"></span>',
            '  <button class="rail-panel__close" type="button" aria-label="关闭">×</button>',
            '</div>',
            '<div class="rail-panel__content" id="rail-panel-content"></div>'
        ].join('');
        titleEl = panelEl.querySelector('.rail-panel__title');
        contentEl = panelEl.querySelector('#rail-panel-content');
        document.body.appendChild(overlayEl);
        document.body.appendChild(panelEl);
        document.body.appendChild(buttonsEl);
        panelEl.querySelector('.rail-panel__close').addEventListener('click', close);
        overlayEl.addEventListener('click', close);
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape') close();
        });
    }
  function createButton(item) {
    var btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'rail-button fx-swap fx-pulse';  // 呼吸
    btn.setAttribute('data-rail-id', item.id);
    btn.setAttribute('aria-label', item.label);
    btn.setAttribute('title', item.label);
    var iconDefault = item.icon || '●';
    var iconActive = item.iconActive || iconDefault;
    btn.innerHTML =
        '<span class="fx-swap__a rail-button__icon fx-text-pulse">' + iconDefault + '</span>' +
        '<span class="fx-swap__b rail-button__icon fx-text-pulse">' + iconActive + '</span>';
    btn.addEventListener('click', function () {
        if (activeId === item.id) {
            close();
        } else {
            open(item);
        }
    });
    return btn;
}
    function highlightButtons() {
        var all = buttonsEl.querySelectorAll('.rail-button');
        for (var i = 0; i < all.length; i++) {
            var id = all[i].getAttribute('data-rail-id');
            all[i].classList.toggle('is-active', id === activeId);
        }
    }
    function open(item) {
        activeId = item.id;
        titleEl.textContent = item.label;
        contentEl.innerHTML = '<p class="rail-panel__loading">加载中…</p>';
        highlightButtons();
        document.body.classList.add('rail-open');
        if (item.html) {
            contentEl.innerHTML = item.html;
            return;
        }
        if (item.template) {
            var api = new mw.Api();
            api.get({
                action: 'parse',
                page: item.template,
                prop: 'text',
                formatversion: '2'
            }).done(function (data) {
                if (activeId !== item.id) return; // 用户切换了按钮
                if (data && data.parse && data.parse.text) {
                    contentEl.innerHTML = data.parse.text;
                } else {
                    contentEl.innerHTML = '<p>加载失败。</p>';
                }
            }).fail(function () {
                if (activeId !== item.id) return;
                contentEl.innerHTML = '<p>加载失败。</p>';
            });
        } else {
            contentEl.innerHTML = '<p>未配置内容。</p>';
        }
    }
    function close() {
        activeId = null;
        document.body.classList.remove('rail-open');
        if (buttonsEl) highlightButtons();
    }
    function init() {
        ensureDOM();
        buttonsEl.innerHTML = '';
        items.forEach(function (item) {
            buttonsEl.appendChild(createButton(item));
        });
    }
    return {
        register: function (id, options) {
            options = options || {};
            items.push({
                id: id,
                icon: options.icon || '●',
                label: options.label || id,
                html: options.html || null,
                template: options.template || null
            });
        },
        init: init,
        open: open,
        close: close
    };
})();
/* ===== 在这里注册工具栏按钮 ===== */
Rail.register('navigation', {
    icon: '☰',
    label: '导航',
    template: 'Template:工具栏导航'
});
Rail.register('claim', {
    icon: '!',
    label: '公告',
    template: 'Template:工具栏公告'
});
Rail.register('help', {
    icon: '?',
    label: '帮助',
    template: 'Template:工具栏帮助'
});
Rail.register('settings', {
    icon: '⚙',
    label: '设置',
    template: 'Template:工具栏设置'
});
/* ===== 初始化 ===== */
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () { Rail.init(); });
} else {
    Rail.init();
}
/* ===== 工具栏账户信息动态填充 ===== */
(function () {
    var HIDDEN_GROUPS = ['*', 'user', 'autoconfirmed', 'emailconfirmed'];
    var GROUP_NAME_FALLBACK = {
        'sysop': '策展人',
        'bureaucrat': '行政员',
        'interface-admin': '织界者',
        'interface_admin': '织界者',
        'user': '旅人',
        'autoconfirmed': '自动确认用户'
    };
    function formatDate(ms) {
        if (!ms) return '—';
        var d = new Date(ms);
        return d.getFullYear() + '-' +
            String(d.getMonth() + 1).padStart(2, '0') + '-' +
            String(d.getDate()).padStart(2, '0');
    }
    function isMissing(msg) {
        if (!msg) return true;
        // 消息未加载时 MediaWiki 会返回 ⧼key⧽ 形式
        return msg.indexOf('\u29FC') !== -1 || msg.indexOf('⧼') !== -1;
    }
    function getGroupName(g) {
        var txt = mw.msg('group-' + g + '-member');
        if (!isMissing(txt)) return txt;
        return GROUP_NAME_FALLBACK[g] || g;
    }
    function getGroupUrl(g) {
        var page = mw.msg('grouppage-' + g);
        if (!isMissing(page)) {
            return mw.util.getUrl(page);
        }
        return mw.util.getUrl('Anachronism:' + getGroupName(g));
    }
    function getGroupHtml(groups) {
        var visible = groups.filter(function (g) {
            return HIDDEN_GROUPS.indexOf(g) === -1;
        });
        if (!visible.length) return '无';
        return visible.map(function (g) {
            var name = getGroupName(g);
            var url = getGroupUrl(g);
            return '<a href="' + url + '" class="rail-group-tag">' + name + '</a>';
        }).join('');
    }
    function renderGuest(box) {
        box.innerHTML = [
            '<div class="rail-account-title">账户</div>',
            '<p class="rail-account-guest">您的身份是访客</p>',
            '<div class="rail-account-actions">',
            '  <a href="' + mw.util.getUrl('Special:UserLogin') + '" class="rail-action-button">登录</a>',
            '  <a href="' + mw.util.getUrl('Special:CreateAccount') + '" class="rail-action-button">创建账户</a>',
            '</div>'
        ].join('');
    }
    function renderUser(box) {
        var userName = mw.config.get('wgUserName');
        var groups = mw.config.get('wgUserGroups') || [];
        var editCount = mw.config.get('wgUserEditCount');
        var regTime = mw.config.get('wgUserRegistration');
        box.innerHTML = [
            '<div class="rail-account-title">账户:' + userName + '</div>',
            '<div class="rail-account-groups">权限组:' + getGroupHtml(groups) + '</div>',
            '<div class="rail-account-actions">',
            '  <a href="' + mw.util.getUrl('Special:Contributions/' + userName) + '" class="rail-action-button">贡献</a>',
            '  <a href="' + mw.util.getUrl('Special:Watchlist') + '" class="rail-action-button">监视列表</a>',
            '  <a href="' + mw.util.getUrl('User talk:' + userName) + '" class="rail-action-button">用户讨论</a>',
            '</div>',
            '<div class="rail-account-stats">',
            '  <span>编辑数:' + (editCount != null ? editCount : '—') + '</span>',
            '  <span>加入时间:' + formatDate(regTime) + '</span>',
            '</div>',
            '<div class="rail-account-logout">',
            '  <a href="' + mw.util.getUrl('Special:UserLogout') + '" class="rail-action-button rail-action-button--danger">退出登录</a>',
            '</div>'
        ].join('');
    }
    function fillAccountInfo() {
        var box = document.getElementById('rail-account-info');
        if (!box || box.dataset.filled === '1') return;
        box.dataset.filled = '1';
        if (mw.config.get('wgUserName')) {
            renderUser(box);
        } else {
            renderGuest(box);
        }
    }
    function observeRailPanel() {
        var target = document.getElementById('rail-panel-content');
        if (!target) return;
        var observer = new MutationObserver(fillAccountInfo);
        observer.observe(target, { childList: true, subtree: true });
        fillAccountInfo();
    }
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', observeRailPanel);
    } else {
        observeRailPanel();
    }
})();
/* ===== 在 rail 面板中触发 Citizen 偏好设置面板 ===== */
(function () {
    function bindRailPreferences() {
        var trigger = document.getElementById('rail-open-preferences');
        if (!trigger || trigger.dataset.bound === '1') return;
        trigger.dataset.bound = '1';
        trigger.addEventListener('click', function () {
            if (window.Rail && typeof Rail.close === 'function') {
                Rail.close();
            }
            var details = document.getElementById('citizen-preferences-details');
            if (details) {
                details.open = true;
            }
            document.body.classList.add('citizen-preferences-shown');
            // 插入关闭按钮(只插一次)
            var card = document.getElementById('citizen-preferences-dropdown__card');
            if (card && !card.querySelector('.citizen-preferences-close')) {
                var closeBtn = document.createElement('button');
                closeBtn.className = 'citizen-preferences-close';
                closeBtn.type = 'button';
                closeBtn.textContent = '×';
                closeBtn.setAttribute('aria-label', '关闭');
                closeBtn.addEventListener('click', function () {
                    document.body.classList.remove('citizen-preferences-shown');
                    var d = document.getElementById('citizen-preferences-details');
                    if (d) d.open = false;
                });
                card.insertBefore(closeBtn, card.firstChild);
            }
        });
    }
    // 点击面板外部关闭
    document.addEventListener('click', function (e) {
        if (!document.body.classList.contains('citizen-preferences-shown')) return;
        var card = document.getElementById('citizen-preferences-dropdown__card');
        var trigger = document.getElementById('rail-open-preferences');
        if (!card) return;
        if (card.contains(e.target)) return;
        if (trigger && trigger.contains(e.target)) return;
        document.body.classList.remove('citizen-preferences-shown');
        var details = document.getElementById('citizen-preferences-details');
        if (details) details.open = false;
    });
    // Esc 关闭
    document.addEventListener('keydown', function (e) {
        if (e.key !== 'Escape') return;
        if (!document.body.classList.contains('citizen-preferences-shown')) return;
        document.body.classList.remove('citizen-preferences-shown');
        var details = document.getElementById('citizen-preferences-details');
        if (details) details.open = false;
    });
    var observer = new MutationObserver(bindRailPreferences);
    observer.observe(document.body, { childList: true, subtree: true });
    bindRailPreferences();
})();
/* ===== 侧边工具栏 Rail 管理器 ===== */
/* ===== 侧边工具栏 Rail 管理器 ===== */
/* ===== 首页轮播图 ===== */
(function () {
    function initHomeCarousel() {
        var carousel = document.getElementById('home-carousel');
        if (!carousel) return;
        var items = carousel.querySelectorAll('.home-carousel-item');
        var dotsBox = document.getElementById('home-carousel-dots');
        var prevBtn = document.getElementById('home-carousel-prev');
        var nextBtn = document.getElementById('home-carousel-next');
        if (!items.length || !dotsBox || !prevBtn || !nextBtn) return;
        var current = 0;
        var timer = null;
        items.forEach(function (_, i) {
            var dot = document.createElement('span');
            dot.className = 'home-carousel-dot' + (i === 0 ? ' active' : '');
            dot.addEventListener('click', function () { goTo(i); });
            dotsBox.appendChild(dot);
        });
        var dots = dotsBox.querySelectorAll('.home-carousel-dot');
        function goTo(index) {
            items[current].classList.remove('active');
            dots[current].classList.remove('active');
            current = (index + items.length) % items.length;
            items[current].classList.add('active');
            dots[current].classList.add('active');
        }
        function next() { goTo(current + 1); }
        function prev() { goTo(current - 1); }
        function startAuto() {
            stopAuto();
            timer = setInterval(next, 5000);
        }
        function stopAuto() {
            if (timer) { clearInterval(timer); timer = null; }
        }
        nextBtn.addEventListener('click', function () { next(); startAuto(); });
        prevBtn.addEventListener('click', function () { prev(); startAuto(); });
        carousel.addEventListener('mouseenter', stopAuto);
        carousel.addEventListener('mouseleave', startAuto);
        startAuto();
    }
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initHomeCarousel);
    } else {
        initHomeCarousel();
    }
})();

2026年9月27日 (日) 23:40的最新版本

/* ===== 侧边工具栏 Rail 管理器 ===== */
/* ===== 侧边工具栏 Rail 管理器 ===== */
window.Rail = (function () {
    var items = [];
    var activeId = null;
    var panelEl, overlayEl, buttonsEl, contentEl, titleEl;

    function ensureDOM() {
        if (document.getElementById('rail-container')) return;

        buttonsEl = document.createElement('div');
        buttonsEl.id = 'rail-container';
        buttonsEl.className = 'rail-container';

        overlayEl = document.createElement('div');
        overlayEl.id = 'rail-overlay';
        overlayEl.className = 'rail-overlay';

        panelEl = document.createElement('aside');
        panelEl.id = 'rail-panel';
        panelEl.className = 'rail-panel';
        panelEl.innerHTML = [
            '<div class="rail-panel__header">',
            '  <span class="rail-panel__title"></span>',
            '  <button class="rail-panel__close" type="button" aria-label="关闭">×</button>',
            '</div>',
            '<div class="rail-panel__content" id="rail-panel-content"></div>'
        ].join('');

        titleEl = panelEl.querySelector('.rail-panel__title');
        contentEl = panelEl.querySelector('#rail-panel-content');

        document.body.appendChild(overlayEl);
        document.body.appendChild(panelEl);
        document.body.appendChild(buttonsEl);

        panelEl.querySelector('.rail-panel__close').addEventListener('click', close);
        overlayEl.addEventListener('click', close);
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape') close();
        });
    }

   function createButton(item) {
    var btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'rail-button fx-swap fx-pulse';   // 呼吸 
    btn.setAttribute('data-rail-id', item.id);
    btn.setAttribute('aria-label', item.label);
    btn.setAttribute('title', item.label);

    var iconDefault = item.icon || '●';
    var iconActive = item.iconActive || iconDefault;

    btn.innerHTML =
        '<span class="fx-swap__a rail-button__icon fx-text-pulse">' + iconDefault + '</span>' +
        '<span class="fx-swap__b rail-button__icon fx-text-pulse">' + iconActive + '</span>';

    btn.addEventListener('click', function () {
        if (activeId === item.id) {
            close();
        } else {
            open(item);
        }
    });
    return btn;
	}

    function highlightButtons() {
        var all = buttonsEl.querySelectorAll('.rail-button');
        for (var i = 0; i < all.length; i++) {
            var id = all[i].getAttribute('data-rail-id');
            all[i].classList.toggle('is-active', id === activeId);
        }
    }

    function open(item) {
        activeId = item.id;
        titleEl.textContent = item.label;
        contentEl.innerHTML = '<p class="rail-panel__loading">加载中…</p>';
        highlightButtons();
        document.body.classList.add('rail-open');

        if (item.html) {
            contentEl.innerHTML = item.html;
            return;
        }

        if (item.template) {
            var api = new mw.Api();
            api.get({
                action: 'parse',
                page: item.template,
                prop: 'text',
                formatversion: '2'
            }).done(function (data) {
                if (activeId !== item.id) return; // 用户切换了按钮
                if (data && data.parse && data.parse.text) {
                    contentEl.innerHTML = data.parse.text;
                } else {
                    contentEl.innerHTML = '<p>加载失败。</p>';
                }
            }).fail(function () {
                if (activeId !== item.id) return;
                contentEl.innerHTML = '<p>加载失败。</p>';
            });
        } else {
            contentEl.innerHTML = '<p>未配置内容。</p>';
        }
    }

    function close() {
        activeId = null;
        document.body.classList.remove('rail-open');
        if (buttonsEl) highlightButtons();
    }

    function init() {
        ensureDOM();
        buttonsEl.innerHTML = '';
        items.forEach(function (item) {
            buttonsEl.appendChild(createButton(item));
        });
    }

    return {
        register: function (id, options) {
            options = options || {};
            items.push({
                id: id,
                icon: options.icon || '●',
                label: options.label || id,
                html: options.html || null,
                template: options.template || null
            });
        },
        init: init,
        open: open,
        close: close
    };
})();

/* ===== 在这里注册工具栏按钮 ===== */
Rail.register('navigation', {
    icon: '☰',
    label: '导航',
    template: 'Template:工具栏导航'
});

Rail.register('claim', {
    icon: '!',
    label: '公告',
    template: 'Template:工具栏公告'
});

Rail.register('help', {
    icon: '?',
    label: '帮助',
    template: 'Template:工具栏帮助'
});

Rail.register('settings', {
    icon: '⚙',
    label: '设置',
    template: 'Template:工具栏设置'
});

/* ===== 初始化 ===== */
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () { Rail.init(); });
} else {
    Rail.init();
}

/* ===== 工具栏账户信息动态填充 ===== */
(function () {
    var HIDDEN_GROUPS = ['*', 'user', 'autoconfirmed', 'emailconfirmed'];

    var GROUP_NAME_FALLBACK = {
        'sysop': '策展人',
        'bureaucrat': '行政员',
        'interface-admin': '织界者',
        'interface_admin': '织界者',
        'user': '旅人',
        'autoconfirmed': '自动确认用户'
    };

    function formatDate(ms) {
        if (!ms) return '—';
        var d = new Date(ms);
        return d.getFullYear() + '-' +
            String(d.getMonth() + 1).padStart(2, '0') + '-' +
            String(d.getDate()).padStart(2, '0');
    }

    function isMissing(msg) {
        if (!msg) return true;
        // 消息未加载时 MediaWiki 会返回 ⧼key⧽ 形式
        return msg.indexOf('\u29FC') !== -1 || msg.indexOf('⧼') !== -1;
    }

    function getGroupName(g) {
        var txt = mw.msg('group-' + g + '-member');
        if (!isMissing(txt)) return txt;
        return GROUP_NAME_FALLBACK[g] || g;
    }

    function getGroupUrl(g) {
        var page = mw.msg('grouppage-' + g);
        if (!isMissing(page)) {
            return mw.util.getUrl(page);
        }
        return mw.util.getUrl('Anachronism:' + getGroupName(g));
    }

    function getGroupHtml(groups) {
        var visible = groups.filter(function (g) {
            return HIDDEN_GROUPS.indexOf(g) === -1;
        });
        if (!visible.length) return '无';

        return visible.map(function (g) {
            var name = getGroupName(g);
            var url = getGroupUrl(g);
            return '<a href="' + url + '" class="rail-group-tag">' + name + '</a>';
        }).join('');
    }

    function renderGuest(box) {
        box.innerHTML = [
            '<div class="rail-account-title">账户</div>',
            '<p class="rail-account-guest">您的身份是访客</p>',
            '<div class="rail-account-actions">',
            '  <a href="' + mw.util.getUrl('Special:UserLogin') + '" class="rail-action-button">登录</a>',
            '  <a href="' + mw.util.getUrl('Special:CreateAccount') + '" class="rail-action-button">创建账户</a>',
            '</div>'
        ].join('');
    }

    function renderUser(box) {
        var userName = mw.config.get('wgUserName');
        var groups = mw.config.get('wgUserGroups') || [];
        var editCount = mw.config.get('wgUserEditCount');
        var regTime = mw.config.get('wgUserRegistration');

        box.innerHTML = [
            '<div class="rail-account-title">账户:' + userName + '</div>',
            '<div class="rail-account-groups">权限组:' + getGroupHtml(groups) + '</div>',
            '<div class="rail-account-actions">',
            '  <a href="' + mw.util.getUrl('Special:Contributions/' + userName) + '" class="rail-action-button">贡献</a>',
            '  <a href="' + mw.util.getUrl('Special:Watchlist') + '" class="rail-action-button">监视列表</a>',
            '  <a href="' + mw.util.getUrl('User talk:' + userName) + '" class="rail-action-button">用户讨论</a>',
            '</div>',
            '<div class="rail-account-stats">',
            '  <span>编辑数:' + (editCount != null ? editCount : '—') + '</span>',
            '  <span>加入时间:' + formatDate(regTime) + '</span>',
            '</div>',
            '<div class="rail-account-logout">',
            '  <a href="' + mw.util.getUrl('Special:UserLogout') + '" class="rail-action-button rail-action-button--danger">退出登录</a>',
            '</div>'
        ].join('');
    }

    function fillAccountInfo() {
        var box = document.getElementById('rail-account-info');
        if (!box || box.dataset.filled === '1') return;
        box.dataset.filled = '1';

        if (mw.config.get('wgUserName')) {
            renderUser(box);
        } else {
            renderGuest(box);
        }
    }

    function observeRailPanel() {
        var target = document.getElementById('rail-panel-content');
        if (!target) return;
        var observer = new MutationObserver(fillAccountInfo);
        observer.observe(target, { childList: true, subtree: true });
        fillAccountInfo();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', observeRailPanel);
    } else {
        observeRailPanel();
    }
})();

/* ===== 在 rail 面板中触发 Citizen 偏好设置面板 ===== */
(function () {
    function bindRailPreferences() {
        var trigger = document.getElementById('rail-open-preferences');
        if (!trigger || trigger.dataset.bound === '1') return;
        trigger.dataset.bound = '1';

        trigger.addEventListener('click', function () {
            if (window.Rail && typeof Rail.close === 'function') {
                Rail.close();
            }

            var details = document.getElementById('citizen-preferences-details');
            if (details) {
                details.open = true;
            }
            document.body.classList.add('citizen-preferences-shown');

            // 插入关闭按钮(只插一次)
            var card = document.getElementById('citizen-preferences-dropdown__card');
            if (card && !card.querySelector('.citizen-preferences-close')) {
                var closeBtn = document.createElement('button');
                closeBtn.className = 'citizen-preferences-close';
                closeBtn.type = 'button';
                closeBtn.textContent = '×';
                closeBtn.setAttribute('aria-label', '关闭');
                closeBtn.addEventListener('click', function () {
                    document.body.classList.remove('citizen-preferences-shown');
                    var d = document.getElementById('citizen-preferences-details');
                    if (d) d.open = false;
                });
                card.insertBefore(closeBtn, card.firstChild);
            }
        });
    }

    // 点击面板外部关闭
    document.addEventListener('click', function (e) {
        if (!document.body.classList.contains('citizen-preferences-shown')) return;
        var card = document.getElementById('citizen-preferences-dropdown__card');
        var trigger = document.getElementById('rail-open-preferences');
        if (!card) return;
        if (card.contains(e.target)) return;
        if (trigger && trigger.contains(e.target)) return;
        document.body.classList.remove('citizen-preferences-shown');
        var details = document.getElementById('citizen-preferences-details');
        if (details) details.open = false;
    });

    // Esc 关闭
    document.addEventListener('keydown', function (e) {
        if (e.key !== 'Escape') return;
        if (!document.body.classList.contains('citizen-preferences-shown')) return;
        document.body.classList.remove('citizen-preferences-shown');
        var details = document.getElementById('citizen-preferences-details');
        if (details) details.open = false;
    });

    var observer = new MutationObserver(bindRailPreferences);
    observer.observe(document.body, { childList: true, subtree: true });
    bindRailPreferences();
})();

/* ===== 侧边工具栏 Rail 管理器 ===== */
/* ===== 侧边工具栏 Rail 管理器 ===== */

/* ===== 首页轮播图 ===== */
(function () {
    function initHomeCarousel() {
        var carousel = document.getElementById('home-carousel');
        if (!carousel) return;

        var items = carousel.querySelectorAll('.home-carousel-item');
        var dotsBox = document.getElementById('home-carousel-dots');
        var prevBtn = document.getElementById('home-carousel-prev');
        var nextBtn = document.getElementById('home-carousel-next');
        if (!items.length || !dotsBox || !prevBtn || !nextBtn) return;

        var current = 0;
        var timer = null;

        items.forEach(function (_, i) {
            var dot = document.createElement('span');
            dot.className = 'home-carousel-dot' + (i === 0 ? ' active' : '');
            dot.addEventListener('click', function () { goTo(i); });
            dotsBox.appendChild(dot);
        });
        var dots = dotsBox.querySelectorAll('.home-carousel-dot');

        function goTo(index) {
            items[current].classList.remove('active');
            dots[current].classList.remove('active');
            current = (index + items.length) % items.length;
            items[current].classList.add('active');
            dots[current].classList.add('active');
        }

        function next() { goTo(current + 1); }
        function prev() { goTo(current - 1); }

        function startAuto() {
            stopAuto();
            timer = setInterval(next, 5000);
        }
        function stopAuto() {
            if (timer) { clearInterval(timer); timer = null; }
        }

        nextBtn.addEventListener('click', function () { next(); startAuto(); });
        prevBtn.addEventListener('click', function () { prev(); startAuto(); });
        carousel.addEventListener('mouseenter', stopAuto);
        carousel.addEventListener('mouseleave', startAuto);

        startAuto();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initHomeCarousel);
    } else {
        initHomeCarousel();
    }
})();