TTV

Công cụ đăng chương hiện đại cho Tàng Thư Viện với UI/UX được tối ưu

当前为 2025-03-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         TTV
// @namespace    http://tampermonkey.net/
// @version      7.2
// @description  Công cụ đăng chương hiện đại cho Tàng Thư Viện với UI/UX được tối ưu
// @author       HA
// @match        https://tangthuvien.net/dang-chuong/story/*
// @match        https://tangthuvien.net/danh-sach-chuong/story/*
// @grant        GM_addStyle
// @grant        GM_setValue 
// @grant        GM_getValue
// @required     https://code.jquery.com/jquery-3.2.1.min.js
// ==/UserScript==

(function() {
    'use strict';

    const headerSign = "";
    const footerSign = "";
    const MAX_CHAPTER_POST = 10;

    let CHAP_NUMBER = 1;
    let CHAP_STT = 1;
    let CHAP_SERIAL = 1;
    let CHAP_NUMBER_ORIGINAL = 1;
    let CHAP_STT_ORIGINAL = 1;
    let CHAP_SERIAL_ORIGINAL = 1;

    // CSS tùy chỉnh
    GM_addStyle(`
        #modern-uploader {
            position: fixed;
            top: 10px;
            right: 10px;
            width: 400px;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
            z-index: 9999;
        }

        #notification-area {
            padding: 0.5rem;
            border-radius: 0.25rem;
            font-weight: bold;
        }

        .notification-success { color: #22c55e; }
        .notification-error { color: #ef4444; }
        .notification-warning { color: #f59e0b; }
        .notification-info { color: #3b82f6; }

        .loading-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9999;
        }

        .loading-spinner {
            width: 40px;
            height: 40px;
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3b82f6;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        #debug-output {
            font-family: monospace;
            white-space: pre;
            font-size: 12px;
            max-height: 200px;
            overflow: auto;
            margin-top: 10px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            background: #f5f5f5;
        }

        .character-counter {
            text-align: right;
            margin-top: 5px;
            font-size: 12px;
            color: #666;
        }
    `);

    // Tạo HTML cho chương mới
    function createChapterHTML(number) {
        const chap_vol = parseInt(jQuery('.chap_vol').val());
        const chap_vol_name = jQuery('.chap_vol_name').val();

        return `
            <div data-gen="MK_GEN" id="COUNT_CHAP_${number}_MK">
                <div class="col-xs-12 form-group"></div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_stt">STT</label>
                    <div class="col-sm-8">
                        <input class="form-control" required name="chap_stt[${number}]" value="${CHAP_STT}"
                            placeholder="Số thứ tự của chương" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_number">Chương thứ..</label>
                    <div class="col-sm-8">
                        <input value="${CHAP_SERIAL}" required class="form-control" name="chap_number[${number}]" 
                            placeholder="Chương thứ.. (1,2,3..)" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Quyển số</label>
                    <div class="col-sm-8">
                        <input class="form-control" name="vol[${number}]" 
                            placeholder="Quyển số" type="number" value="${chap_vol}" required/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Tên quyển</label>
                    <div class="col-sm-8">
                        <input class="form-control chap_vol_name" name="vol_name[${number}]" 
                            placeholder="Tên quyển" type="text" value="${chap_vol_name}" />
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Tên chương</label>
                    <div class="col-sm-8">
                        <input required class="form-control" name="chap_name[${number}]" 
                            placeholder="Tên chương" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="introduce">Nội dung</label>
                    <div class="col-sm-8">
                        <textarea maxlength="75000" style="color:#000;font-weight: 400;" required class="form-control chapter-content"
                            name="introduce[${number}]" rows="20" placeholder="Nội dung" type="text"></textarea>
                        <div class="character-counter" style="text-align: right; margin-top: 5px; font-size: 12px; color: #666;">
                            <span class="current-count">0</span>/20.000 ký tự
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="adv">Quảng cáo</label>
                    <div class="col-sm-8">
                        <textarea maxlength="1000" class="form-control" name="adv[${number}]" 
                            placeholder="Quảng cáo" type="text"></textarea>
                    </div>
                </div>
            </div>`;
    }

    // Thêm chương mới
    function addNewChapter() {
        if ((CHAP_NUMBER + 1) <= MAX_CHAPTER_POST) {
            updateChapNumber(true);
            const html = createChapterHTML(CHAP_NUMBER);
            jQuery('#add-chap').before(html);
            setupCharacterCounter(); // Add this line to initialize counter for new chapters
        } else {
            showNotification(`Chỉ có thể đăng tối đa ${MAX_CHAPTER_POST} chương một lần`, 'warning');
        }
    }

    // Cập nhật số chương
    function updateChapNumber(isAdd) {
        try {
            if (isAdd) {
                let maxStt = 0;
                let maxSerial = 0;

                // Tìm giá trị lớn nhất trong tất cả các input hiện có
                jQuery('input[name^="chap_stt"]').each(function() {
                    const val = parseInt(jQuery(this).val()) || 0;
                    maxStt = Math.max(maxStt, val);
                });

                jQuery('input[name^="chap_number"]').each(function() {
                    const val = parseInt(jQuery(this).val()) || 0;
                    maxSerial = Math.max(maxSerial, val);
                });

                // So sánh với giá trị từ DOM
                const chapStt = parseInt(jQuery('.chap_stt1').val()) || 0;
                const chapSerial = parseInt(jQuery('.chap_serial').val()) || 0;

                maxStt = Math.max(maxStt, chapStt);
                maxSerial = Math.max(maxSerial, chapSerial);

                // Cập nhật biến đếm
                CHAP_STT = maxStt + 1;
                CHAP_SERIAL = maxSerial + 1;
                CHAP_NUMBER++;
            } else {
                if (CHAP_NUMBER > CHAP_NUMBER_ORIGINAL) {
                    CHAP_NUMBER--;
                }
                if (CHAP_STT > CHAP_STT_ORIGINAL) {
                    CHAP_STT--;
                }
                if (CHAP_SERIAL > CHAP_SERIAL_ORIGINAL) {
                    CHAP_SERIAL--;
                }
            }

            jQuery('#chap_number').val(CHAP_NUMBER);
            jQuery('#chap_stt').val(CHAP_STT);
            jQuery('#chap_serial').val(CHAP_SERIAL);
            jQuery('#countNumberPost').text(CHAP_NUMBER);
        } catch (e) {
            console.log("Lỗi: " + e);
        }
    }

    // Tạo giao diện chính
    function createInterface() {
        const container = document.createElement('div');
        container.id = 'modern-uploader';
        container.innerHTML = `
            <div class="text-center mb-4">
                <h3 class="text-xl font-bold">CÔNG CỤ ĐĂNG NHANH</h3>
                <p id="short-chapter-warning" class="text-red-500 mt-2 hidden"></p>
            </div>

            <div class="form-group">
                <textarea id="qpContent" class="form-control" rows="5" 
                    placeholder="Dán nội dung truyện vào đây để tự động tách chương"></textarea>
            </div>

            <div class="debug-info" style="display: none;">
                <pre id="debug-output"></pre>
            </div>

            <div class="flex justify-between">
                <button class="btn btn-outline" id="qpButtonRemoveEmpty">Xóa chương trống</button>
                <button class="btn btn-primary" id="qpButtonSubmit">Đăng chương</button>
            </div>

            <div id="notification-area" class="mt-3 text-center"></div>
        `;

        jQuery(".list-in-user").before(container);
        setupEventListeners();
    }

    // Khởi tạo các chương
    function initializeChapters() {
        showLoading();
        try {
            const chap_number = parseInt(jQuery('#chap_number').val());
            let chap_stt = parseInt(jQuery('.chap_stt1').val());
            let chap_serial = parseInt(jQuery('.chap_serial').val());

            if (parseInt(jQuery('#chap_stt').val()) > chap_stt) {
                chap_stt = parseInt(jQuery('#chap_stt').val());
            }
            if (parseInt(jQuery('#chap_serial').val()) > chap_serial) {
                chap_serial = parseInt(jQuery('#chap_serial').val());
            }

            CHAP_NUMBER = CHAP_NUMBER_ORIGINAL = chap_number;
            CHAP_STT = CHAP_STT_ORIGINAL = chap_stt;
            CHAP_SERIAL = CHAP_SERIAL_ORIGINAL = chap_serial;

            // Thêm 9 chương mới
            for(let i = 0; i < 9; i++) {
                addNewChapter();
            }

            hideLoading();
            showNotification('Đã tạo đủ 10 chương');
        } catch (e) {
            console.log("Lỗi: " + e);
            hideLoading();
            showNotification('Có lỗi khi tạo chương', 'error');
        }
    }

    // Khởi tạo các event listener
    function setupEventListeners() {
        // Xử lý paste nội dung
        jQuery("#qpContent").on("paste", function (e) {
            e.preventDefault();
            jQuery(this).val("");
            showLoading();

            const pastedText = e.originalEvent.clipboardData.getData('text');
            jQuery(this).val(pastedText);

            setTimeout(function() {
                const chapters = performAction();
                hideLoading();
                showNotification(`Đã nhập ${chapters} chương`, 'success');
            }, 100);
        });

        jQuery('#qpButtonRemoveEmpty').on('click', removeEmptyChapters);
        jQuery('#qpButtonSubmit').on('click', submitChapters);
    }

    // Xử lý paste và tách chương
    function performAction() {
        try {
            console.log("Starting performAction");
            var text = jQuery("#qpContent").val();

            if (!text) {
                showNotification('Không có nội dung để tách chương', 'error');
                return 0;
            }

            var debugOutput = [];
            var chapters = [];
            var lines = text.split('\n');
            var currentChapter = [];
            var lastTitle = null;

            debugOutput.push("=== Processing Text ===");
            debugOutput.push(`Total lines: ${lines.length}`);
            debugOutput.push("=== Line Analysis ===");

            // Helper function to show exact whitespace
            function visualizeWhitespace(str) {
                return str.split('').map(c => {
                    if (c === '\t') return '\\t';
                    if (c === ' ') return '·';
                    if (c === '\n') return '\\n';
                    return c;
                }).join('');
            }

            for (let i = 0; i < lines.length; i++) {
                let line = lines[i];
                let isChapterTitle = /^\t[Cc]hương\s*\d+\s*:/.test(line) || /^\s{4,}[Cc]hương\s*\d+\s*:/.test(line);

                // Debug log with exact whitespace
                debugOutput.push(`Line ${i}: ${visualizeWhitespace(line.substring(0, 50))}${line.length > 50 ? '...' : ''}`);
                debugOutput.push(`  Is chapter: ${isChapterTitle}`);

                if (isChapterTitle) {
                    if (currentChapter.length > 0) {
                        if (line !== lastTitle) {
                            chapters.push(currentChapter.join('\n'));
                            currentChapter = [line];
                            lastTitle = line;
                            debugOutput.push(`  -> New chapter started`);
                        } else {
                            debugOutput.push(`  -> Skipped duplicate title`);
                        }
                    } else {
                        currentChapter = [line];
                        lastTitle = line;
                        debugOutput.push(`  -> First chapter started`);
                    }
                } else if (currentChapter.length > 0) {
                    currentChapter.push(line);
                }
            }

            if (currentChapter.length > 0) {
                chapters.push(currentChapter.join('\n'));
                debugOutput.push("-> Added final chapter");
            }

            debugOutput.push("=== Results ===");
            debugOutput.push(`Found ${chapters.length} chapters`);

            // Phân tách chương dài
            const processedChapters = [];
            for (let i = 0; i < chapters.length; i++) {
                const chapterLines = chapters[i].split('\n');
                const title = chapterLines.shift().trim();
                const chapterText = chapterLines.join('\n');

                // Đếm số ký tự của chương
                const charCount = chapterText.length;
                debugOutput.push(`Chapter ${i+1} character count: ${charCount}`);

                // Nếu chương có kích thước lớn hơn 20000 ký tự, chia nhỏ
                if (charCount > 20000) {
                    // Số chương cần tách
                    const parts = Math.ceil(charCount / 20000);
                    debugOutput.push(`Splitting into ${parts} parts`);

                    // Tính số ký tự cho mỗi phần
                    const charsPerPart = Math.ceil(charCount / parts);
                    debugOutput.push(`Characters per part: ~${charsPerPart}`);

                    // Chia chương thành các phần đều nhau dựa trên số ký tự
                    let currentText = chapterText;
                    let totalProcessed = 0;

                    for (let part = 0; part < parts; part++) {
                        // Xác định kích thước phần này
                        const isLastPart = part === parts - 1;
                        const targetSize = isLastPart ? currentText.length : charsPerPart;

                        // Tìm điểm kết thúc phù hợp (kết thúc câu hoặc đoạn văn)
                        let endPos = Math.min(targetSize, currentText.length);

                        // Tìm điểm kết thúc là cuối đoạn văn hoặc cuối câu gần với vị trí mục tiêu
                        if (!isLastPart && endPos < currentText.length) {
                            // Tìm vị trí xuống dòng gần nhất
                            const nextParagraph = currentText.indexOf('\n\n', endPos - 500);
                            if (nextParagraph !== -1 && nextParagraph < endPos + 500) {
                                endPos = nextParagraph + 2; // +2 để bao gồm cả ký tự xuống dòng
                            } else {
                                // Nếu không tìm thấy đoạn văn, tìm dấu kết thúc câu
                                const sentenceEnd = Math.max(
                                    currentText.lastIndexOf('. ', endPos),
                                    currentText.lastIndexOf('! ', endPos),
                                    currentText.lastIndexOf('? ', endPos)
                                );

                                if (sentenceEnd !== -1 && sentenceEnd > endPos - 500) {
                                    endPos = sentenceEnd + 2; // +2 để bao gồm dấu kết thúc câu và khoảng trắng
                                }
                            }
                        }

                        // Lấy nội dung của phần này
                        const partContent = currentText.substring(0, endPos);
                        totalProcessed += partContent.length;

                        // Cập nhật text còn lại cho phần tiếp theo
                        currentText = currentText.substring(endPos);

                        // Tạo tiêu đề phần: chỉ lấy tiêu đề gốc và thêm phần chia
                        let chapterTitle = title;
                        if (title.includes(':')) {
                            chapterTitle = title.substring(title.indexOf(':') + 1).trim();
                        }

                        // Thêm thông tin phần vào tiêu đề gốc
                        let newTitle = `${title} (Phần ${part+1}/${parts})`;
                        processedChapters.push(newTitle + '\n' + partContent);

                        debugOutput.push(`Part ${part+1}: ${partContent.length} chars`);
                    }

                    debugOutput.push(`Total processed: ${totalProcessed}/${charCount} chars`);
                } else {
                    // Giữ nguyên chương nếu không cần chia
                    processedChapters.push(chapters[i]);
                }
            }

            debugOutput.push(`After processing: ${processedChapters.length} chapters`);

            // Giới hạn chỉ lấy 10 chương đầu tiên vào form, phần còn lại sẽ copy vào clipboard
            const chaptersToFill = processedChapters.slice(0, MAX_CHAPTER_POST);
            const remainingChapters = processedChapters.slice(MAX_CHAPTER_POST);

            // Fill chapters into forms
            var titles = jQuery("input[name^='chap_name']");
            var contents = jQuery("textarea[name^='introduce']");
            var advs = jQuery("textarea[name^='adv']");

            debugOutput.push(`Forms found: ${titles.length}`);

            if (processedChapters.length === 0) {
                showNotification('Không tìm thấy chương nào', 'error');
                jQuery('#debug-output').text(debugOutput.join('\n'));
                return;
            }

            // Nếu có chương còn lại, sao chép vào clipboard
            if (remainingChapters.length > 0) {
                debugOutput.push(`${remainingChapters.length} chapters will be copied to clipboard`);
            }

            // Tạo thêm form nếu số chương cần điền nhiều hơn số form hiện có
            const neededForms = chaptersToFill.length - titles.length;
            if (neededForms > 0 && titles.length < MAX_CHAPTER_POST) {
                debugOutput.push(`Need to add ${neededForms} more forms`);
                for (let i = 0; i < neededForms && (titles.length + i) < MAX_CHAPTER_POST; i++) {
                    addNewChapter();
                }
                // Cập nhật lại danh sách các form sau khi thêm
                titles = jQuery("input[name^='chap_name']");
                contents = jQuery("textarea[name^='introduce']");
                advs = jQuery("textarea[name^='adv']");
            }

            debugOutput.push(`Filling ${chaptersToFill.length} chapters into forms`);

            // Điền nội dung vào form
            jQuery.each(titles, function(k, v) {
                if (k < chaptersToFill.length) {
                    var content = chaptersToFill[k].split('\n');
                    var title = content.shift().trim();
                    //Preserve the "Chương X:" prefix
                    var originalTitle = title;


                    debugOutput.push(`\nFilling chapter ${k + 1}:`);
                    debugOutput.push(`Original title: ${title}`);
                    debugOutput.push(`Extracted title: ${originalTitle}`);
                    debugOutput.push(`Content length: ${content.length} lines`);

                    titles[k].value = originalTitle;
                    contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                    if (advs[k]) advs[k].value = "";

                    // Trigger character counter update
                    jQuery(contents[k]).trigger('input');
                }
            });

            // Sao chép các chương còn lại vào clipboard nếu có
            if (remainingChapters.length > 0) {
                try {
                    // Tạo nội dung clipboard với định dạng rõ ràng để dễ phân biệt các chương
                    const clipboardContent = remainingChapters.map(chap => chap.trim()).join('\n\n---CHAPTER_SEPARATOR---\n\n');

                    // Thử trước với Clipboard API (hiện đại)
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        navigator.clipboard.writeText(clipboardContent)
                            .then(() => {
                                debugOutput.push(`Đã sao chép ${remainingChapters.length} chương vào clipboard (Clipboard API)`);
                                showNotification(`Đã sao chép ${remainingChapters.length} chương vào clipboard`, 'success');
                            })
                            .catch(err => {
                                throw err; // Chuyển đến phương pháp dự phòng
                            });
                    } else {
                        // Phương pháp dự phòng với execCommand (cũ)
                        const tempTextarea = document.createElement('textarea');
                        tempTextarea.style.position = 'fixed';
                        tempTextarea.style.top = '0';
                        tempTextarea.style.left = '0';
                        tempTextarea.style.width = '2em';
                        tempTextarea.style.height = '2em';
                        tempTextarea.style.opacity = '0';
                        tempTextarea.style.pointerEvents = 'none';
                        tempTextarea.value = clipboardContent;

                        document.body.appendChild(tempTextarea);
                        tempTextarea.focus();
                        tempTextarea.select();

                        const successful = document.execCommand('copy');
                        document.body.removeChild(tempTextarea);

                        if (!successful) {
                            throw new Error('Không thể sao chép vào clipboard');
                        }

                        debugOutput.push(`Đã sao chép ${remainingChapters.length} chương vào clipboard (execCommand)`);
                        showNotification(`Đã sao chép ${remainingChapters.length} chương vào clipboard`, 'success');
                    }
                } catch (err) {
                    console.error('Lỗi khi sao chép vào clipboard:', err);
                    debugOutput.push(`Lỗi khi sao chép vào clipboard: ${err.message}`);
                    showNotification('Không thể sao chép vào clipboard. Vui lòng thử lại.', 'error');

                    // Hiển thị textarea để copy thủ công nếu tự động không thành công
                    const manualCopyArea = document.createElement('div');
                    manualCopyArea.style.position = 'fixed';
                    manualCopyArea.style.top = '50%';
                    manualCopyArea.style.left = '50%';
                    manualCopyArea.style.transform = 'translate(-50%, -50%)';
                    manualCopyArea.style.backgroundColor = 'white';
                    manualCopyArea.style.padding = '20px';
                    manualCopyArea.style.borderRadius = '8px';
                    manualCopyArea.style.boxShadow = '0 4px 6px -1px rgba(0, 0, 0, 0.1)';
                    manualCopyArea.style.zIndex = '10000';
                    manualCopyArea.style.maxWidth = '80%';
                    manualCopyArea.style.maxHeight = '80%';
                    manualCopyArea.style.overflow = 'auto';

                    manualCopyArea.innerHTML = `
                        <h3 style="margin-top: 0;">Sao chép thủ công</h3>
                        <p>Không thể sao chép tự động. Vui lòng chọn toàn bộ nội dung bên dưới và sao chép (Ctrl+C):</p>
                        <textarea style="width: 100%; height: 300px; padding: 10px;">${clipboardContent}</textarea>
                        <div style="text-align: right; margin-top: 10px;">
                            <button id="closeManualCopy" style="padding: 8px 16px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer;">Đóng</button>
                        </div>
                    `;

                    document.body.appendChild(manualCopyArea);

                    document.getElementById('closeManualCopy').addEventListener('click', () => {
                        document.body.removeChild(manualCopyArea);
                    });
                }
            }

            jQuery("#qpButtonSubmit").removeClass("btn-disable").addClass("btn-success");
            jQuery("#qpContent").val("Đã thực hiện xong");

            // Hiển thị thông báo sau khi xử lý xong
            if (remainingChapters.length > 0) {
                let message = `Đã sử lý ${chapters.length} chương\n`;
                message += `Đã nhập ${MAX_CHAPTER_POST} chương\n`;
                message += `Đã coppy ${remainingChapters.length} chương`;

                // Đếm số chương được chia
                let splitChapters = 0;
                for (let i = 0; i < chapters.length; i++) {
                    const chapterText = chapters[i].split('\n').slice(1).join('\n');
                    if (chapterText.length > 20000) {
                        splitChapters++;
                    }
                }

                if (processedChapters.length > chapters.length) {
                    message += `\nCó ${splitChapters} chương chia thành ${processedChapters.length - (chapters.length - splitChapters)} chương`;
                }

                showNotification(message, 'success');
            } else if (processedChapters.length > chapters.length) {
                // Đếm số chương được chia
                let splitChapters = 0;
                for (let i = 0; i < chapters.length; i++) {
                    const chapterText = chapters[i].split('\n').slice(1).join('\n');
                    if (chapterText.length > 20000) {
                        splitChapters++;
                    }
                }

                let message = `Đã sử lý ${chapters.length} chương\n`;
                message += `Đã nhập ${processedChapters.length} chương\n`;
                message += `Có ${splitChapters} chương chia thành ${processedChapters.length - (chapters.length - splitChapters)} chương`;
                showNotification(message, 'success');
            } else {
                showNotification(`Đã sử lý ${chapters.length} chương\nĐã nhập ${processedChapters.length} chương vào form`, 'success');
            }

            // Show debug output
            jQuery('#debug-output').text(debugOutput.join('\n'));

            return processedChapters.length;
        } catch (e) {
            console.error("Error in performAction:", e);
            showNotification('Có lỗi khi tách chương', 'error');
            return 0;
        }
    }

    // Xóa chương trống
    function removeEmptyChapters() {
        const forms = document.querySelectorAll('[data-gen="MK_GEN"]');
        let removed = 0;

        forms.forEach(form => {
            const content = form.querySelector('textarea[name^="introduce"]').value.trim();
            if (!content) {
                form.remove();
                removed++;
                updateChapNumber(false);
            }
        });

        showNotification(`Đã xử lý ${forms.length} chương`, 'info');
    }

    // Đăng chương
    function submitChapters() {
        const forms = document.querySelectorAll('[data-gen="MK_GEN"]');
        let hasError = false;

        forms.forEach(form => {
            const contentTextarea = form.querySelector('textarea[name^="introduce"]');
            const content = contentTextarea.value;
            if (content.length < 3000) {
                // Đánh dấu form với màu đỏ rõ ràng hơn
                contentTextarea.style.border = '3px solid #ff0000';
                contentTextarea.style.backgroundColor = 'rgba(255, 0, 0, 0.08)';
                // Đổi màu chữ để dễ đọc hơn trên nền đỏ
                contentTextarea.style.color = '#cc0000';
                // Thêm đường viền ngoài cho parent để làm nổi bật toàn bộ form
                contentTextarea.parentNode.style.border = '1px solid #ff0000';
                contentTextarea.parentNode.style.padding = '5px';
                contentTextarea.parentNode.style.borderRadius = '5px';
                contentTextarea.parentNode.style.backgroundColor = 'rgba(255, 0, 0, 0.03)';
                hasError = true;

                // Thêm thông báo lỗi bên dưới textarea nổi bật hơn
                let errorMsg = form.querySelector('.chapter-length-error');
                if (!errorMsg) {
                    errorMsg = document.createElement('div');
                    errorMsg.className = 'chapter-length-error';
                    errorMsg.style.color = '#ff0000';
                    errorMsg.style.marginTop = '5px';
                    errorMsg.style.fontSize = '14px';
                    errorMsg.style.fontWeight = 'bold';
                    errorMsg.style.padding = '5px 10px';
                    errorMsg.style.backgroundColor = '#fff0f0';
                    errorMsg.style.border = '1px solid #ff0000';
                    errorMsg.style.borderRadius = '3px';
                    contentTextarea.parentNode.appendChild(errorMsg);
                }
                errorMsg.textContent = `⚠️ Chương quá ngắn: ${content.length}/3000 ký tự cần thiết`;
            } else {
                // Reset tất cả các style khi chương đủ dài
                contentTextarea.style.border = '';
                contentTextarea.style.backgroundColor = '';
                contentTextarea.style.color = '';
                contentTextarea.parentNode.style.border = '';
                contentTextarea.parentNode.style.padding = '';
                contentTextarea.parentNode.style.borderRadius = '';
                contentTextarea.parentNode.style.backgroundColor = '';

                // Xóa thông báo lỗi nếu có
                const errorMsg = form.querySelector('.chapter-length-error');
                if (errorMsg) {
                    errorMsg.remove();
                }
            }
        });

        if (hasError) {
            showNotification('Có chương ngắn hơn 3000 ký tự, vui lòng kiểm tra các ô màu đỏ', 'error');
            return;
        }

        showLoading();
        // Submit form gốc
        document.querySelector('form[name="postChapForm"] button[type="submit"]').click();
        setTimeout(hideLoading, 2000);
    }

    // Hiển thị thông báo
    function showNotification(message, type = 'info') {
        const notificationArea = document.getElementById('notification-area');
        // Chuyển đổi xuống dòng thành thẻ <br> để hiển thị đúng trong HTML
        notificationArea.innerHTML = message.replace(/\n/g, '<br>');
        notificationArea.className = `mt-3 text-center notification-${type}`;
        // Thêm padding để thông báo đẹp hơn khi hiển thị nhiều dòng
        notificationArea.style.padding = '10px';
    }

    // Hiển thị loading
    function showLoading() {
        const loading = document.createElement('div');
        loading.className = 'loading-overlay';
        loading.innerHTML = `
            <div class="loading-spinner"></div>
        `;
        document.body.appendChild(loading);
    }

    function hideLoading() {
        const loading = document.querySelector('.loading-overlay');
        if (loading) {
            loading.remove();
        }
    }

    //Setup character counter
    function setupCharacterCounter() {
        jQuery('.chapter-content').on('input', function() {
            const textarea = jQuery(this);
            const currentCount = textarea.val().length;
            textarea.next('.character-counter').find('.current-count').text(currentCount);

            // Hiển thị số ký tự
            const counterElement = textarea.next('.character-counter');

            // Cảnh báo nếu chương quá dài
            if (currentCount > 20000) {
                counterElement.css('color', '#ff6600');
                if (counterElement.find('.char-warning').length === 0) {
                    counterElement.append(`<div class="char-warning" style="color: #ff6600; font-weight: bold;">Chương này dài (>2000 ký tự), sẽ được tự động chia khi đăng</div>`);
                }
            } else {
                counterElement.css('color', '#666');
                counterElement.find('.word-warning').remove();
            }
        });

        // Trigger input event để cập nhật counters cho các textarea đã có nội dung
        jQuery('.chapter-content').trigger('input');
    }

    // Khởi tạo script
    function init() {
        createInterface();
        initializeChapters();
        setupCharacterCounter(); // Initialize character counters on page load
    }

    init();
})();