TTV Auto Upload

Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         TTV Auto Upload
// @namespace    http://tampermonkey.net/
// @version      3.7
// @description  Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao
// @author       HA
// @match        https://tangthuvien.net/dang-chuong/story/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // CSS cho thông báo và control panel
    const style = document.createElement('style');
    style.textContent = `
        .ttv-notification {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 20px;
            background: #4CAF50;
            color: white;
            border-radius: 4px;
            z-index: 9999;
            display: none;
        }
        .ttv-error {
            background: #f44336;
        }
        .ttv-control-panel {
            position: fixed;
            top: 50px;
            right: 20px;
            background: white;
            padding: 25px;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
            z-index: 9998;
            width: 500px;
            margin-bottom: 20px;
            transition: all 0.3s ease;
        }
        .ttv-control-panel.minimized {
            width: auto;
            height: auto;
            padding: 10px;
            opacity: 0.8;
            transform: translateX(calc(100% - 40px));
            transition: all 0.3s ease;
        }
        .ttv-control-panel.minimized:hover {
            opacity: 1;
            transform: translateX(0);
        }
        .ttv-control-panel.minimized .ttv-button-group,
        .ttv-control-panel.minimized .ttv-header {
            display: none;
        }
        .ttv-button-group {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        .ttv-content-editor {
            width: 100%;
            height: 100px;
            margin: 6px 0;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 13px;
            line-height: 1.4;
            resize: vertical;
            transition: all 0.2s ease;
        }
        .ttv-content-editor:focus {
            border-color: #5bc0de;
            outline: none;
            box-shadow: 0 0 8px rgba(91,192,222,0.2);
        }
        .ttv-preview {
            display: none;
            width: 100%;
            height: 100px;
            margin: 6px 0;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 13px;
            line-height: 1.4;
            overflow-y: auto;
            background: #f9f9f9;
            transition: all 0.2s ease;
        }
        .ttv-heading {
            font-size: 15px;
            color: #555;
            margin: 12px 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .ttv-word-count {
            font-size: 12px;
            color: #888;
            padding: 3px 8px;
            background: #f5f5f5;
            border-radius: 4px;
            transition: all 0.2s ease;
        }
        .ttv-chapter-list {
            width: 100%;
            margin: 10px 0;
            max-height: 200px;
            overflow-y: auto;
            border: 1px solid #eee;
            border-radius: 6px;
            padding: 8px;
        }
        .ttv-chapter-item {
            padding: 8px;
            border-bottom: 1px solid #eee;
            cursor: pointer;
            transition: all 0.2s ease;
            line-height: 1.4;
            font-size: 12px;
            color: #666;
        }
        .ttv-chapter-item .chapter-title {
            font-weight: bold;
            margin-bottom: 4px;
        }
        .ttv-chapter-item .chapter-name {
            color: #888;
            padding-left: 10px;
            border-left: 2px solid #ddd;
            margin: 4px 0;
        }
        .ttv-chapter-item .chapter-stats {
            font-size: 11px;
            color: #999;
        }
        .ttv-chapter-item:last-child {
            border-bottom: none;
        }
        .ttv-chapter-item.selected {
            background: #f0f8ff;
            border-left: 2px solid #5bc0de;
        }
        .ttv-control-panel.fullscreen {
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 0;
            z-index: 9999;
            padding: 15px;
            display: flex;
            flex-direction: column;
        }
        .ttv-control-panel.fullscreen .ttv-content-editor,
        .ttv-control-panel.fullscreen .ttv-preview {
            height: calc(100vh - 250px);
            margin: 15px 0;
            font-size: 16px;
        }
        .ttv-header {
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #eee;
            font-weight: bold;
            font-size: 16px;
            color: #444;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        button.btn-warning {
            background: #f0ad4e;
            color: white;
            border: none;
            padding: 12px;
            border-radius: 6px;
            width: 100%;
            font-size: 14px;
            transition: all 0.2s ease;
        }
        button.btn-warning:hover {
            background: #ec971f;
            transform: translateY(-1px);
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        button.ttv-minimize {
            padding: 2px 8px;
            background: none;
            border: none;
            cursor: pointer;
            font-size: 16px;
            color: #666;
            transition: all 0.2s ease;
        }
        button.ttv-minimize:hover {
            color: #333;
        }
    `;
    document.head.appendChild(style);

    // Tạo div thông báo
    const notification = document.createElement('div');
    notification.className = 'ttv-notification';
    document.body.appendChild(notification);

    // Hiển thị thông báo
    function showNotification(message, isError = false) {
        notification.textContent = message;
        notification.className = 'ttv-notification' + (isError ? ' ttv-error' : '');
        notification.style.display = 'block';
        setTimeout(() => {
            notification.style.display = 'none';
        }, 3000);
    }

    // Parse chapters function update
    function parseChapters(content) {
        const lines = content.split('\n');
        const chapters = [];
        let currentChapter = {
            title: '',
            name: '',
            content: []
        };

        const chapterPattern = /^\s*Chương\s+\d+:/;
        let previousChapterTitle = '';

        // Find chapters with clear markers
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i].trim();

            if (chapterPattern.test(line)) {
                // Check if it's a duplicate header
                if (line !== previousChapterTitle) {
                    // Log for debug
                    console.log(`Tìm thấy chương mới: ${line}`);

                    // If there was a previous chapter, save it
                    if (currentChapter.title && currentChapter.content.length > 0) {
                        chapters.push({...currentChapter});
                        console.log(`Đã lưu chương: ${currentChapter.title}\nTên: ${currentChapter.name}\nSố dòng: ${currentChapter.content.length}`);
                        currentChapter = {title: '', name: '', content: []};
                    }

                    // Save current chapter title
                    currentChapter.title = line;
                    // Get chapter name after :
                    let name = line.split(':')[1]?.trim() || '';
                    // Remove punctuation from start and end of chapter name
                    name = name.replace(/^[.,;'"]+|[.,;'"]+$/g, '').trim();
                    currentChapter.name = name;
                    previousChapterTitle = line;

                    console.log(`Đang xử lý chương mới:\nTiêu đề: ${line}\nTên chương: ${name}`);
                } else {
                    console.log(`Bỏ qua tiêu đề trùng lặp: ${line}`);
                }
            } else {
                // Save all non-chapter-title content
                if (line) { // Only add non-empty lines
                    if (currentChapter.title) {
                        currentChapter.content.push(line);
                    }
                }
            }
        }

        // Add the last chapter if exists
        if (currentChapter.title && currentChapter.content.length > 0) {
            chapters.push({...currentChapter});
        }

        // Display chapters and auto fill forms
        if (chapters.length > 0) {
            displayChapters(chapters);
            // Auto fill forms
            setTimeout(() => {
                try {
                    transferContent();
                } catch (error) {
                    console.error('Lỗi khi tự động điền form:', error);
                    showNotification('Có lỗi xảy ra khi tự động điền form!', true);
                }
            }, 1000);
        }

        console.log(`Tổng số chương tìm thấy: ${chapters.length}`);
        return chapters;
    }

    // Thêm function createChapterHTML
    function createChapterHTML(chapNum) {
        const chap_vol = parseInt(jQuery('.chap_vol').val()) || 1;
        const chap_vol_name = jQuery('.chap_vol_name').val() || '';
        return `
        <div data-gen="MK_GEN" id="COUNT_CHAP_${chapNum}_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[${chapNum}]" value="${dăngnhanhTTV.STATE.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="${dăngnhanhTTV.STATE.CHAP_SERIAL}" required class="form-control" name="chap_number[${chapNum}]" 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[${chapNum}]" 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[${chapNum}]" 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[${chapNum}]" 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" name="introduce[${chapNum}]" rows="20" placeholder="Nội dung" type="text"></textarea>
                    <div class="chapter-character-count"></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[${chapNum}]" placeholder="Quảng cáo" type="text"></textarea>
                </div>
            </div>
        </div>`;
    }

    // Add state management
    const dăngnhanhTTV = {
        STATE: {
            CHAP_NUMBER: 1,
            CHAP_STT: 1,
            CHAP_SERIAL: 1,
            CHAP_NUMBER_ORIGINAL: 1,
            CHAP_STT_ORIGINAL: 1,
            CHAP_SERIAL_ORIGINAL: 1
        },
        initializeChapterValues: function() {
            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());
                }

                this.STATE.CHAP_NUMBER = this.STATE.CHAP_NUMBER_ORIGINAL = chap_number || 1;
                this.STATE.CHAP_STT = this.STATE.CHAP_STT_ORIGINAL = chap_stt || 1;
                this.STATE.CHAP_SERIAL = this.STATE.CHAP_SERIAL_ORIGINAL = chap_serial || 1;
            } catch (e) {
                console.error("Error initializing chapter values:", e);
            }
        }
    };

    // Update transferContent function to use createChapterHTML
    async function transferContent() {
        try {
            console.log("Bắt đầu quá trình chuyển nội dung");
            
            // Get all chapters
            const chapterItems = document.querySelectorAll('.ttv-chapter-item');
            if (!chapterItems.length) {
                throw new Error('Không tìm thấy chương nào để điền vào form');
            }
            console.log(`Tìm thấy ${chapterItems.length} chương để điền vào form`);

            // Find the form container
            const form = document.querySelector('form[name="postChapForm"]');
            if (!form) {
                throw new Error('Không tìm thấy form đăng chương');
            }
            console.log("Tìm thấy form đăng chương");

            // Get and update state values
            let chap_vol = 1;
            let chap_vol_name = '';
            
            try {
                chap_vol = parseInt(jQuery('.chap_vol').val()) || 1;
                chap_vol_name = jQuery('.chap_vol_name').val() || '';
                console.log(`Đã lấy thông tin quyển: số ${chap_vol}, tên: ${chap_vol_name}`);
            } catch (e) {
                console.warn("Không thể lấy thông tin quyển, sử dụng giá trị mặc định", e);
            }

            // Tìm STT chương và số thứ tự cao nhất trong form hiện tại
            let maxChapStt = 0;
            let maxChapSerial = 0;
            
            try {
                // Tìm tất cả các form chương hiện có
                const existingForms = form.querySelectorAll('[id^="COUNT_CHAP_"]');
                console.log(`Tìm thấy ${existingForms.length} form chương hiện có`);
                
                // Tìm STT và số thứ tự cao nhất
                existingForms.forEach(formElem => {
                    try {
                        // Lấy index từ ID của form, ví dụ: COUNT_CHAP_1_MK -> 1
                        const formIdMatch = formElem.id.match(/COUNT_CHAP_(\d+)_MK/);
                        if (formIdMatch && formIdMatch[1]) {
                            const formIndex = parseInt(formIdMatch[1]);
                            
                            // Lấy giá trị STT
                            const sttInput = formElem.querySelector(`input[name="chap_stt[${formIndex}]"]`);
                            if (sttInput && sttInput.value && !isNaN(parseInt(sttInput.value))) {
                                const sttVal = parseInt(sttInput.value);
                                if (sttVal > maxChapStt) {
                                    maxChapStt = sttVal;
                                }
                            }
                            
                            // Lấy giá trị số thứ tự
                            const serialInput = formElem.querySelector(`input[name="chap_number[${formIndex}]"]`);
                            if (serialInput && serialInput.value && !isNaN(parseInt(serialInput.value))) {
                                const serialVal = parseInt(serialInput.value);
                                if (serialVal > maxChapSerial) {
                                    maxChapSerial = serialVal;
                                }
                            }
                        }
                    } catch (formError) {
                        console.warn("Lỗi khi đọc giá trị từ form:", formError);
                    }
                });
                
                console.log(`STT chương cao nhất tìm thấy: ${maxChapStt}, Số thứ tự cao nhất: ${maxChapSerial}`);
                
                // Cập nhật state với giá trị cao nhất tìm được
                if (maxChapStt > 0) {
                    dăngnhanhTTV.STATE.CHAP_STT = maxChapStt;
                }
                
                if (maxChapSerial > 0) {
                    dăngnhanhTTV.STATE.CHAP_SERIAL = maxChapSerial;
                }
                
            } catch (e) {
                console.warn("Không thể tìm STT và số thứ tự cao nhất, sử dụng giá trị mặc định", e);
            }
            
            // Đếm số form chương hiện có để xác định index bắt đầu
            const existingFormCount = form.querySelectorAll('[id^="COUNT_CHAP_"]').length;
            console.log(`Số form chương hiện có: ${existingFormCount}`);

            console.log(`Bắt đầu tạo ${chapterItems.length} form chương mới từ index ${existingFormCount + 1}`);

            // Tạo form cho mỗi chương
            for (let i = 0; i < chapterItems.length; i++) {
                const formIndex = existingFormCount + i + 1;
                console.log(`Đang tạo form cho chương ${formIndex}`);

                try {
                    // Tăng các giá trị STT và số thứ tự cho chương mới
                    dăngnhanhTTV.STATE.CHAP_STT++;
                    dăngnhanhTTV.STATE.CHAP_SERIAL++;
                    
                    console.log(`Sử dụng STT: ${dăngnhanhTTV.STATE.CHAP_STT}, Số thứ tự: ${dăngnhanhTTV.STATE.CHAP_SERIAL}`);
                    
                    // Tạo HTML cho form chương mới
                    const chapterHTML = createChapterHTML(formIndex);
                    const tempDiv = document.createElement('div');
                    tempDiv.innerHTML = chapterHTML;
                    const newFormElement = tempDiv.firstElementChild;
                    
                    if (!newFormElement) {
                        throw new Error(`Không thể tạo element form cho chương ${formIndex}`);
                    }
                    
                    form.appendChild(newFormElement);
                    console.log(`Đã thêm form HTML cho chương ${formIndex}`);
                    
                    // Lấy thông tin chương
                    const chapterItem = chapterItems[i];
                    
                    if (!chapterItem) {
                        throw new Error(`Không tìm thấy dữ liệu cho chương ${formIndex}`);
                    }
                    
                    const titleElement = chapterItem.querySelector('.chapter-title');
                    const nameElement = chapterItem.querySelector('.chapter-name');
                    
                    if (!titleElement || !nameElement) {
                        throw new Error(`Thiếu thông tin tiêu đề hoặc tên cho chương ${formIndex}`);
                    }
                    
                    const chapterTitle = titleElement.textContent;
                    const chapterName = nameElement.textContent.replace('Tên chương: ', '');
                    const chapterNumberMatch = chapterTitle.match(/Chương\s+(\d+)/);
                    const chapterNumber = chapterNumberMatch ? chapterNumberMatch[1] : dăngnhanhTTV.STATE.CHAP_SERIAL.toString();
                    
                    console.log(`Thông tin chương ${formIndex}: Tiêu đề: ${chapterTitle}, Tên: ${chapterName}, Số: ${chapterNumber}`);

                    // Lấy các trường form
                    const formFields = {
                        chapterName: form.querySelector(`input[name="chap_name[${formIndex}]"]`),
                        content: form.querySelector(`textarea[name="introduce[${formIndex}]"]`),
                        chapterNumber: form.querySelector(`input[name="chap_number[${formIndex}]"]`),
                        chapterOrder: form.querySelector(`input[name="chap_stt[${formIndex}]"]`),
                        volume: form.querySelector(`input[name="vol[${formIndex}]"]`),
                        volumeName: form.querySelector(`input[name="vol_name[${formIndex}]"]`),
                        advertisement: form.querySelector(`textarea[name="adv[${formIndex}]"]`)
                    };

                    // Kiểm tra xem có thiếu trường nào không
                    const missingFields = [];
                    for (const [fieldName, element] of Object.entries(formFields)) {
                        if (!element) {
                            missingFields.push(fieldName);
                        }
                    }

                    if (missingFields.length > 0) {
                        throw new Error(`Thiếu các trường ${missingFields.join(', ')} trong form ${formIndex}`);
                    }

                    // Điền dữ liệu vào form
                    formFields.chapterName.value = chapterName;
                    formFields.chapterNumber.value = dăngnhanhTTV.STATE.CHAP_SERIAL.toString();
                    formFields.chapterOrder.value = dăngnhanhTTV.STATE.CHAP_STT.toString();
                    formFields.volume.value = chap_vol;
                    formFields.volumeName.value = chap_vol_name;
                    
                    // Kiểm tra và gán nội dung
                    if (chapterItem._content) {
                        formFields.content.value = chapterItem._content;
                    } else {
                        console.warn(`Chương ${formIndex} không có nội dung`);
                        formFields.content.value = '';
                    }
                    
                    formFields.advertisement.value = '';

                    console.log(`Đã điền form cho chương ${formIndex}: Tên: ${chapterName}, STT: ${dăngnhanhTTV.STATE.CHAP_STT}, Số thứ tự: ${dăngnhanhTTV.STATE.CHAP_SERIAL}, Độ dài nội dung: ${formFields.content.value.length} ký tự`);

                    // Kích hoạt sự kiện input để cập nhật số đếm ký tự
                    try {
                        const inputEvent = new Event('input', { bubbles: true });
                        formFields.content.dispatchEvent(inputEvent);
                    } catch (inputError) {
                        console.warn(`Không thể kích hoạt sự kiện input cho chương ${formIndex}:`, inputError);
                    }
                } catch (chapterError) {
                    console.error(`Lỗi khi xử lý chương ${formIndex}:`, chapterError);
                    showNotification(`Lỗi ở chương ${formIndex}: ${chapterError.message}`, true);
                    // Tiếp tục với chương tiếp theo thay vì dừng toàn bộ quá trình
                }
            }

            showNotification(`Đã tự động điền ${chapterItems.length} chương vào form!`);
            console.log(`Đã hoàn thành việc điền ${chapterItems.length} chương vào form`);

        } catch (error) {
            console.error('Lỗi khi điền form:', error);
            showNotification('Có lỗi xảy ra khi điền form: ' + error.message, true);
        }
    }

    // Chọn chương để hiển thị
    function selectChapter(chapter, index) {
        const contentEditor = document.querySelector('.ttv-content-editor');
        contentEditor.value = chapter.title + '\n' + chapter.content.join('\n');

        // Cập nhật số từ
        const wordCountSpan = document.querySelector('.ttv-word-count');
        if (wordCountSpan) {
            wordCountSpan.textContent = updateWordCount(contentEditor.value);
        }

        // Highlight selected chapter
        const chapterItems = document.querySelectorAll('.ttv-chapter-item');
        chapterItems.forEach(item => item.classList.remove('selected'));
        chapterItems[index]?.classList.add('selected');

        // Tự động điền form khi chọn chương
        try {
            transferContent();
        } catch (error) {
            console.error('Lỗi khi tự động điền form:', error);
            showNotification('Có lỗi xảy ra khi tự động điền form!', true);
        }
    }

    // Hiển thị danh sách chương
    function displayChapters(chapters) {
        const chapterList = document.createElement('div');
        chapterList.className = 'ttv-chapter-list';

        chapters.forEach((chapter, index) => {
            const chapterItem = document.createElement('div');
            chapterItem.className = 'ttv-chapter-item';

            // Store chapter content
            chapterItem._content = chapter.title + '\n' + chapter.content.join('\n');

            // Tạo các phần tử con với định dạng riêng
            const titleDiv = document.createElement('div');
            titleDiv.className = 'chapter-title';
            titleDiv.textContent = chapter.title;

            const nameDiv = document.createElement('div');
            nameDiv.className = 'chapter-name';
            nameDiv.textContent = `Tên chương: ${chapter.name}`;

            const statsDiv = document.createElement('div');
            statsDiv.className = 'chapter-stats';
            statsDiv.textContent = `${chapter.content.length} dòng`;

            // Thêm các phần tử vào item
            chapterItem.appendChild(titleDiv);
            chapterItem.appendChild(nameDiv);
            chapterItem.appendChild(statsDiv);

            chapterItem.onclick = () => selectChapter(chapter, index);
            chapterList.appendChild(chapterItem);

            // Select first chapter by default
            if (index === 0) {
                chapterItem.classList.add('selected');
            }
        });

        const existingList = document.querySelector('.ttv-chapter-list');
        if (existingList) {
            existingList.remove();
        }

        const contentEditor = document.querySelector('.ttv-content-editor');
        contentEditor.parentNode.insertBefore(chapterList, contentEditor);

        // Hiển thị thông báo về số chương tìm thấy
        showNotification(`Đã tìm thấy ${chapters.length} chương và tự động điền vào form.`);

        // Tự động chọn chương đầu tiên
        if (chapters.length > 0) {
            selectChapter(chapters[0], 0);
        }
    }

    // Đếm số từ và ký tự
    function updateWordCount(content) {
        const wordCount = content.trim().split(/\s+/).length;
        const charCount = content.length;
        return `${wordCount} từ | ${charCount} ký tự`;
    }

    // Chuyển đổi giữa chế độ soạn thảo và xem trước
    function togglePreview() {
        const contentEditor = document.querySelector('.ttv-content-editor');
        const preview = document.querySelector('.ttv-preview');
        const previewBtn = document.querySelector('.ttv-preview-btn');

        if (contentEditor.style.display !== 'none') {
            contentEditor.style.display = 'none';
            preview.style.display = 'block';
            preview.innerHTML = contentEditor.value.replace(/\n/g, '<br>');
            previewBtn.textContent = 'Soạn thảo';
        } else {
            contentEditor.style.display = 'block';
            preview.style.display = 'none';
            previewBtn.textContent = 'Xem trước';
        }
    }

    // Chuyển đổi chế độ toàn màn hình
    function toggleFullscreen() {
        const panel = document.querySelector('.ttv-control-panel');
        const fullscreenBtn = document.querySelector('.ttv-fullscreen-btn');
        panel.classList.toggle('fullscreen');
        fullscreenBtn.textContent = panel.classList.contains('fullscreen') ? 'Thu nhỏ' : 'Toàn màn hình';
    }

    // Thêm panel điều khiển
    function addControlPanel() {
        // Tạo panel
        const panel = document.createElement('div');
        panel.className = 'ttv-control-panel';

        // Thêm header
        const header = document.createElement('div');
        header.className = 'ttv-header';
        header.innerHTML = `
            <div>Soạn Thảo Nội Dung</div>
            <div class="ttv-toolbar">
                <button class="ttv-preview-btn" onclick="togglePreview()">Xem trước</button>
                <button class="ttv-fullscreen-btn" onclick="toggleFullscreen()">Toàn màn hình</button>
                <button class="ttv-minimize">−</button>
            </div>
        `;

        const buttonGroup = document.createElement('div');
        buttonGroup.className = 'ttv-button-group';

        // Khung soạn thảo nội dung
        const contentEditorLabel = document.createElement('div');
        contentEditorLabel.className = 'ttv-heading';
        contentEditorLabel.innerHTML = `
            Nội dung chương:
            <span class="ttv-word-count">0 từ | 0 ký tự</span>
        `;

        const contentEditor = document.createElement('textarea');
        contentEditor.className = 'ttv-content-editor';
        contentEditor.placeholder = 'Nhập hoặc dán nội dung chương vào đây...';

        // Khung xem trước
        const preview = document.createElement('div');
        preview.className = 'ttv-preview';

        // Cập nhật số từ khi nhập nội dung
        contentEditor.oninput = () => {
            const wordCountSpan = document.querySelector('.ttv-word-count');
            if (wordCountSpan) {
                wordCountSpan.textContent = updateWordCount(contentEditor.value);
            }
        };

        // Xử lý khi paste nội dung
        contentEditor.onpaste = (e) => {
            // Cho phép paste hoàn tất
            setTimeout(() => {
                const content = contentEditor.value;
                const chapters = parseChapters(content);
                if (chapters.length > 0) {
                    displayChapters(chapters);
                    // Tự động điền form sau khi hiển thị danh sách chương
                    setTimeout(() => {
                        try {
                            transferContent();
                        } catch (error) {
                            console.error('Lỗi khi tự động điền form:', error);
                            showNotification('Có lỗi xảy ra khi tự động điền form!', true);
                        }
                    }, 1000); // Đợi 1s để đảm bảo UI đã được cập nhật hoàn toàn
                }
            }, 0);
        };

        // Nút chuyển nội dung
        const transferBtn = document.createElement('button');
        transferBtn.type = 'button';
        transferBtn.className = 'btn btn-warning';
        transferBtn.innerHTML = '<span>Chuyển nội dung sang form</span>';
        transferBtn.onclick = transferContent;

        // Thêm các phần tử vào panel
        panel.appendChild(header);
        buttonGroup.appendChild(contentEditorLabel);
        buttonGroup.appendChild(contentEditor);
        buttonGroup.appendChild(preview);
        buttonGroup.appendChild(transferBtn);
        panel.appendChild(buttonGroup);

        document.body.appendChild(panel);

        // Thêm xử lý sự kiện cho các nút trong toolbar
        const minimizeBtn = panel.querySelector('.ttv-minimize');
        minimizeBtn.onclick = () => {
            panel.classList.toggle('minimized');
            minimizeBtn.innerHTML = panel.classList.contains('minimized') ? '+' : '−';
        };

        window.togglePreview = togglePreview;
        window.toggleFullscreen = toggleFullscreen;
    }

    // Initialize chapter values when page loads
    window.addEventListener('load', function() {
        dăngnhanhTTV.initializeChapterValues();
        addControlPanel();
    });
})();