Tự động nhập QLCV NTSoft

Tự động nhập công việc

// ==UserScript==
// @name         Tự động nhập QLCV NTSoft
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Tự động nhập công việc
// @match        https://qlcv.nhattamsoft.vn/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    debugger;

    //===============================================
    // CẤU HÌNH CHUNG - ĐIỀU CHỈNH CÁC GIÁ TRỊ TẠI ĐÂY
    //===============================================

    // Giá trị cần điền vào form
    const FORM_VALUES = {

        MucTieu: 'Nhập tiêu đề',
        NoiDung: 'Nhập nội dung',
        // Chổ này để nhập tiến độ
        NoiDungBC: 'Nội dung',
        KetQuaThucHien: 'Hoàn thành mục tiêu trong ngày',


        TieuDe: '',
        GioGiao: '07:30',
        GioThucHien: '07:30',
        GioHanChot: '17:00',
        GioKetThuc_KL: '17:00',
        UocThoiGianThucHien: '1',
        KhoiLuongYeuCau: '1',
        DiemKPI: '15',
        // Giá trị cho form tiến độ
        KLDotNay: '1',
        DiemTuDanhGia: '15'
    };

    // Thông tin đăng nhập
    const CONFIG = {
        username: '',
        password: '',
        debugMode: true,
        waitTime: 2000 // thời gian chờ (ms) giữa các thao tác
    };

    // Thông tin nhân viên
    const EMPLOYEE_DATA = {
        NguyenHoangVinh: {
            id: 'e5afdda0-8303-4836-9caf-212e9475cbb3',
            code: 'NV0006',
            name: 'Nguyễn Hoàng Vịnh'
        },
        TranVanTrung: {
            id: '1fea906f-9b16-4197-a370-18a52e314ccf',
            code: 'NV0002',
            name: 'Trần Văn Trung'
        }
    };

    // Thông tin danh mục (đơn vị tính, phân loại...)
    const CATEGORY_DATA = {
        PhanLoai: {
            SanXuat: {
                id: '720acd46-7701-4603-ac37-8de641fddb7c',
                code: '030',
                name: 'Sản xuất'
            }
        },
        DonViTinh: {
            CongViec: {
                id: 'd3beaae5-3adc-446a-886f-0d95678eda27',
                name: 'Công việc'
            }
        },
        MucUuTien: {
            MucMot: {
                value: 'Ưu tiên mức 1',
                name: 'Ưu tiên mức 1'
            }
        },
        MucDoCongViec: {
            TrungBinh: {
                value: 'Trung bình',
                name: 'Trung bình'
            }
        }
    };

    // ID của các trường trên form HTML
    const FORM_FIELDS = {
        // Thông tin cơ bản
        TieuDe: 'TieuDe',
        MucTieu: 'MucTieu',
        NoiDung: 'NoiDung',

        // Các dropdown
        MucUuTien: 'UuTien',
        PhanLoai: 'PhanLoaiID',
        MucDoCongViec: 'MucDoCongViec',
        NguoiGiao: 'NhanVienID_NguoiGiao', // ID chính xác từ HTML
        NguoiGiamSat: 'NhanVienID_NguoiGiamSat',
        NguoiTheoDoi: 'NguoiTheoDoi',
        DonViTinh: 'selDonViTinh',

        // Ngày giờ
        NgayGiao: 'NgayGiao',
        GioGiao: 'GioGiao',
        NgayThucHien: 'NgayThucHien',
        GioThucHien: 'GioThucHien',
        HanChot: 'HanChot',
        GioHanChot: 'GioHanChot',
        GioKetThuc_KL: 'GioKetThuc_KL',

        // Thông tin khác
        UocThoiGianThucHien: 'UocThoiGianThucHien',
        KhoiLuongYeuCau: 'KhoiLuongYeuCau',
        KLYeuCau: 'KLYeuCau',
        DiemKPI: 'DiemKPI',

        // Nút thao tác
        ThemMoi: 'btnThemMoi',

        // Các trường form tiến độ
        NoiDungBC: 'NoiDungBC',
        KetQuaThucHien: 'KetQuaThucHien',
        KLDotNay: 'KLDotNay',
        DiemTuDanhGia: 'DiemTuDanhGia',
        NguoiPheDuyet: 'NhanVienID_PheDuyet_modal'
    };



    //===============================================
    // HÀM TIỆN ÍCH - KHÔNG CẦN CHỈNH SỬA
    //===============================================

    // Hàm lấy ngày hiện tại định dạng dd/mm/yyyy
    function getCurrentDate() {
        const today = new Date();
        const day = String(today.getDate()).padStart(2, '0');
        const month = String(today.getMonth() + 1).padStart(2, '0');
        const year = today.getFullYear();
        return `${day}/${month}/${year}`;
    }

    // Ghi log hoạt động
    function log(message) {
        if (CONFIG.debugMode) {
            console.log(`[${new Date().toLocaleTimeString()}] ${message}`);
        }
    }

    // Hàm chọn giá trị trong dropdown
    function selectOption(selectElement, textToSelect) {
        for (let i = 0; i < selectElement.options.length; i++) {
            if (selectElement.options[i].text.includes(textToSelect)) {
                selectElement.selectedIndex = i;
                selectElement.dispatchEvent(new Event('change'));
                return true;
            }
        }
        return false;
    }

    // Hàm chọn giá trị trong select2 dropdown bằng UUID
    function selectByUUID(selectId, uuid) {
        log(`Chọn ${selectId} với UUID: ${uuid}`);

        // Sử dụng select2 API nếu có
        if (typeof $ !== 'undefined' && $.fn.select2) {
            $('#' + selectId).val(uuid).trigger('change');
            return true;
        }

        // Thủ công nếu không có jQuery
        const selectElement = document.getElementById(selectId);
        if (selectElement) {
            for (let i = 0; i < selectElement.options.length; i++) {
                if (selectElement.options[i].value === uuid) {
                    selectElement.selectedIndex = i;
                    selectElement.dispatchEvent(new Event('change'));
                    return true;
                }
            }
        }
        return false;
    }

    // Hàm chọn giá trị trong select2 dropdown bằng mã (code)
    function selectByCode(selectId, code) {
        const selectElement = document.getElementById(selectId);
        if (selectElement) {
            for (let i = 0; i < selectElement.options.length; i++) {
                if (selectElement.options[i].text === code) {
                    selectElement.selectedIndex = i;
                    selectElement.dispatchEvent(new Event('change'));
                    return true;
                }
            }
        }
        return false;
    }

    // Hàm điền giá trị đơn giản vào ô input
    function fillInputField(fieldId, value) {
        const field = document.getElementById(fieldId);
        if (field) {
            field.value = value;
            // Kích hoạt sự kiện để đảm bảo form validation hoạt động
            field.dispatchEvent(new Event('input', { bubbles: true }));
            field.dispatchEvent(new Event('change', { bubbles: true }));
            return true;
        }
        return false;
    }

    // Hàm chính xác để chọn người theo dõi
    function selectNguoiTheoDoi() {
        log("Đang xử lý người theo dõi...");

        // Phương pháp 1: Chọn chính xác từ UUID
        try {
            const nguoiTheoDoiElement = document.getElementById(FORM_FIELDS.NguoiTheoDoi);

            if (nguoiTheoDoiElement) {
                // Sử dụng UUID chính xác
                const trungValue = EMPLOYEE_DATA.TranVanTrung.id;
                const vinhValue = EMPLOYEE_DATA.NguyenHoangVinh.id;

                // Thiết lập giá trị đã chọn
                for (let i = 0; i < nguoiTheoDoiElement.options.length; i++) {
                    const option = nguoiTheoDoiElement.options[i];
                    if (option.value === trungValue || option.value === vinhValue) {
                        option.selected = true;
                        log("Đã chọn giá trị: " + option.value);
                    }
                }

                // Trigger change event
                nguoiTheoDoiElement.dispatchEvent(new Event('change'));

                // Sử dụng Select2 API nếu có
                if (typeof $ !== 'undefined' && $.fn.select2) {
                    $('#' + FORM_FIELDS.NguoiTheoDoi).val([trungValue, vinhValue]).trigger('change');
                }

                return true;
            }
        } catch (e) {
            log("Lỗi khi sử dụng UUID cho người theo dõi: " + e.message);
        }

        // Phương pháp 2: Sử dụng JavaScript để thêm vào Select2 đã hiển thị
        try {
            // Chọn giá trị bằng cách tạo sự kiện click trực tiếp
            const select2Container = document.querySelector('.select2-container');

            if (select2Container) {
                // Mô phỏng click để mở dropdown
                select2Container.querySelector('.select2-selection').click();

                // Tạo một hàm để chọn một người từ dropdown
                const selectPerson = (name, callback) => {
                    setTimeout(() => {
                        const searchInput = document.querySelector('.select2-search__field');
                        if (searchInput) {
                            // Xóa giá trị hiện tại và nhập tên mới
                            searchInput.value = '';
                            searchInput.focus();
                            searchInput.value = name;

                            // Kích hoạt sự kiện input để tìm kiếm
                            const inputEvent = new Event('input', { bubbles: true });
                            searchInput.dispatchEvent(inputEvent);

                            // Đợi kết quả tìm kiếm và nhấp vào tùy chọn đầu tiên
                            setTimeout(() => {
                                const firstOption = document.querySelector('.select2-results__option');
                                if (firstOption) {
                                    firstOption.click();
                                    if (callback) callback();
                                }
                            }, 300);
                        }
                    }, 300);
                };

                // Thêm cả hai người lần lượt
                selectPerson(EMPLOYEE_DATA.NguyenHoangVinh.name, () => {
                    // Sau khi chọn người đầu tiên, chọn người thứ hai
                    setTimeout(() => {
                        select2Container.querySelector('.select2-selection').click();
                        selectPerson(EMPLOYEE_DATA.TranVanTrung.name);
                    }, 500);
                });

                return true;
            }
        } catch (e) {
            log("Lỗi khi sử dụng phương pháp tương tác: " + e.message);
        }

        return false;
    }

    // Hàm điền nội dung với CKEditor (nếu có)
    function fillCKEditor(editorName, content) {
        try {
            if (typeof CKEDITOR !== 'undefined' && CKEDITOR.instances[editorName]) {
                CKEDITOR.instances[editorName].setData(content);
                return true;
            }
        } catch (e) {
            log("Lỗi khi điền CKEditor: " + e.message);
        }
        return false;
    }

    // Hàm điền thông tin vào form thêm công việc
    function fillTaskForm() {
        log("Bắt đầu điền thông tin công việc...");

        // Tên công việc
        fillInputField(FORM_FIELDS.TieuDe, FORM_VALUES.TieuDe);

        // Mục tiêu
        fillInputField(FORM_FIELDS.MucTieu, FORM_VALUES.MucTieu);

        // Nội dung với CKEditor
        if (!fillCKEditor(FORM_FIELDS.NoiDung, FORM_VALUES.NoiDung)) {
            fillInputField(FORM_FIELDS.NoiDung, FORM_VALUES.NoiDung);
        }

        // Mức ưu tiên: Ưu tiên mức 1
        if (document.getElementById(FORM_FIELDS.MucUuTien)) {
            // Sử dụng select2 nếu có
            if (typeof $ !== 'undefined' && $.fn.select2) {
                $('#' + FORM_FIELDS.MucUuTien).val(CATEGORY_DATA.MucUuTien.MucMot.value).trigger('change');
            } else {
                selectOption(document.getElementById(FORM_FIELDS.MucUuTien), CATEGORY_DATA.MucUuTien.MucMot.name);
            }
        }

        // Phân loại: Sản xuất (030)
        if (document.getElementById(FORM_FIELDS.PhanLoai)) {
            // Thử phương pháp 1: Sử dụng UUID
            selectByUUID(FORM_FIELDS.PhanLoai, CATEGORY_DATA.PhanLoai.SanXuat.id);

            // Dự phòng: Thử tìm kiếm bằng mã
            if (!document.querySelector('#select2-' + FORM_FIELDS.PhanLoai + '-container')?.textContent.includes(CATEGORY_DATA.PhanLoai.SanXuat.name)) {
                selectByCode(FORM_FIELDS.PhanLoai, CATEGORY_DATA.PhanLoai.SanXuat.code);
            }
        }

        // Mức độ công việc: Trung bình
        if (document.getElementById(FORM_FIELDS.MucDoCongViec)) {
            selectOption(document.getElementById(FORM_FIELDS.MucDoCongViec), CATEGORY_DATA.MucDoCongViec.TrungBinh.name);
        }

        // Ngày giao: ngày hiện tại
        fillInputField(FORM_FIELDS.NgayGiao, getCurrentDate());

        // Giờ giao: 7:30
        fillInputField(FORM_FIELDS.GioGiao, FORM_VALUES.GioGiao);

        // Người giao: Nguyễn Hoàng Vịnh (NV0006)
        if (document.getElementById(FORM_FIELDS.NguoiGiao)) {
            selectByUUID(FORM_FIELDS.NguoiGiao, EMPLOYEE_DATA.NguyenHoangVinh.id);
        }

        // Ngày thực hiện: ngày hiện tại
        fillInputField(FORM_FIELDS.NgayThucHien, getCurrentDate());

        // Giờ thực hiện: 7:30
        fillInputField(FORM_FIELDS.GioThucHien, FORM_VALUES.GioThucHien);

        // Người giám sát: Nguyễn Hoàng Vịnh (NV0006)
        if (document.getElementById(FORM_FIELDS.NguoiGiamSat)) {
            selectByUUID(FORM_FIELDS.NguoiGiamSat, EMPLOYEE_DATA.NguyenHoangVinh.id);
        }

        // Đơn vị tính: Công việc
        if (document.getElementById(FORM_FIELDS.DonViTinh)) {
            selectByUUID(FORM_FIELDS.DonViTinh, CATEGORY_DATA.DonViTinh.CongViec.id);
        }

        // Deadline: Ngày hiện tại
        fillInputField(FORM_FIELDS.HanChot, getCurrentDate());

        // Giờ deadline: 17:00
        fillInputField(FORM_FIELDS.GioHanChot, FORM_VALUES.GioHanChot);

        // Giờ kết thúc khối lượng: 17:00
        fillInputField(FORM_FIELDS.GioKetThuc_KL, FORM_VALUES.GioKetThuc_KL);

        // Ước thời gian thực hiện: 1 ngày
        fillInputField(FORM_FIELDS.UocThoiGianThucHien, FORM_VALUES.UocThoiGianThucHien);

        // Khối lượng yêu cầu: 1
        fillInputField(FORM_FIELDS.KhoiLuongYeuCau, FORM_VALUES.KhoiLuongYeuCau);

        // Khối lượng yêu cầu (ID thay thế): 1
        fillInputField(FORM_FIELDS.KLYeuCau, FORM_VALUES.KhoiLuongYeuCau);

        // Điểm KPI: 15
        fillInputField(FORM_FIELDS.DiemKPI, FORM_VALUES.DiemKPI);

        // Xử lý người theo dõi với chính xác thông tin
        setTimeout(selectNguoiTheoDoi, 1000);

        log("Hoàn tất điền thông tin công việc");
    }

    // Hàm điền thông tin vào form tiến độ
    function fillProgressForm() {
        log("Bắt đầu điền thông tin tiến độ...");

        // Điền nội dung báo cáo
        fillInputField(FORM_FIELDS.NoiDungBC, FORM_VALUES.NoiDungBC);

        // Điền kết quả thực hiện
        fillInputField(FORM_FIELDS.KetQuaThucHien, FORM_VALUES.KetQuaThucHien);

        // Điền khối lượng đợt này
        fillInputField(FORM_FIELDS.KLDotNay, FORM_VALUES.KLDotNay);

        // Điền điểm tự đánh giá
        fillInputField(FORM_FIELDS.DiemTuDanhGia, FORM_VALUES.DiemTuDanhGia);

        // Chọn người phê duyệt: Nguyễn Hoàng Vịnh (NV0006)
        if (document.getElementById(FORM_FIELDS.NguoiPheDuyet)) {
            setTimeout(() => {
                selectByUUID(FORM_FIELDS.NguoiPheDuyet, EMPLOYEE_DATA.NguyenHoangVinh.id);
                log("Đã chọn người phê duyệt: " + EMPLOYEE_DATA.NguyenHoangVinh.name);
            }, 500);
        }

        log("Hoàn tất điền thông tin tiến độ");
    }

    //===============================================
    // XỬ LÝ SỰ KIỆN CHÍNH
    //===============================================

    // Chờ DOM tải xong
    window.addEventListener('load', function() {
        // Kiểm tra nếu URL là trang đăng nhập
        if (window.location.href.includes("Login.aspx") || window.location.href.includes("dang-nhap.html")) {
            log("Đang ở trang đăng nhập...");

            // Điền thông tin vào form
            document.getElementById('txtusername').value = CONFIG.username;
            document.getElementById('txtpassword').value = CONFIG.password;

            // Click nút đăng nhập
            document.getElementById('btnDangNhap').click();
        }

        // Nếu đang ở trang chủ
        if (window.location.href.includes("ho-so-cong-viec.html")) {
            log("Đang ở trang chủ...");

            // Thêm nút tự động thêm công việc
            const autoButton = document.createElement('button');
            autoButton.textContent = 'Tự động thêm công việc';
            autoButton.style.position = 'fixed';
            autoButton.style.top = '10px';
            autoButton.style.right = '10px';
            autoButton.style.zIndex = '9999';
            autoButton.style.backgroundColor = 'green';
            autoButton.style.color = 'white';
            autoButton.style.padding = '10px';
            autoButton.style.border = 'none';
            autoButton.style.borderRadius = '5px';
            autoButton.style.cursor = 'pointer';

            autoButton.addEventListener('click', function() {
                // Click nút thêm mới
                const themMoiBtn = document.getElementById(FORM_FIELDS.ThemMoi);
                if (themMoiBtn) {
                    log("Click nút thêm mới...");
                    themMoiBtn.click();

                    // Chờ form load xong rồi điền thông tin
                    setTimeout(fillTaskForm, CONFIG.waitTime);
                }
            });

            document.body.appendChild(autoButton);

            // Thêm nút tự động nhập tiến độ
            const progressButton = document.createElement('button');
            progressButton.textContent = 'Tự động nhập tiến độ';
            progressButton.style.position = 'fixed';
            progressButton.style.top = '50px'; // Đặt bên dưới nút trước đó
            progressButton.style.right = '10px';
            progressButton.style.zIndex = '9999';
            progressButton.style.backgroundColor = 'blue';
            progressButton.style.color = 'white';
            progressButton.style.padding = '10px';
            progressButton.style.border = 'none';
            progressButton.style.borderRadius = '5px';
            progressButton.style.cursor = 'pointer';

            progressButton.addEventListener('click', function() {
                document.getElementById('TabKhoiLuongMain').click();
                document.getElementById('btnThemMoiTienDo').click();

                // Chờ form tiến độ load xong rồi điền thông tin
                setTimeout(fillProgressForm, CONFIG.waitTime);
            });

            document.body.appendChild(progressButton);
        }

        // Nếu đang ở trang thêm mới hoặc trang cập nhật công việc
        if (window.location.href.includes('them-cong-viec') || window.location.href.includes('cap-nhat-cong-viec')) {
            log("Đang ở trang thêm/cập nhật công việc...");
            // Đợi form load xong
            setTimeout(fillTaskForm, CONFIG.waitTime);
        }
    });
})();