Hệ thống pháp luật

ỦY BAN NHÂN DÂN
TỈNH BÀ RỊA - VŨNG TÀU
-------

CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM
Độc lập - Tự do - Hạnh phúc
---------------

Số: 242/KH-UBND

Bà Rịa - Vũng Tàu, ngày 21 tháng 11 năm 2023

 

KẾ HOẠCH

TRIỂN KHAI THỰC HIỆN ĐỀ ÁN “PHÁT TRIỂN HỆ THỐNG ĐÁNH GIÁ DIỆN RỘNG CẤP QUỐC GIA ĐÁP ỨNG YÊU CẦU NÂNG CAO CHẤT LƯỢNG VÀ HỘI NHẬP QUỐC TẾ CỦA GIÁO DỤC PHỔ THÔNG GIAI ĐOẠN 2022-2030”

Thực hiện Quyết định số 468/QĐ-BGDĐT ngày 13/02/2023 của Bộ Giáo dục và Đào tạo (GDĐT) về việc phê duyệt Đề án “Phát triển hệ thống đánh giá diện rộng cấp quốc gia đáp ứng yêu cầu nâng cao chất lượng và hội nhập quốc tế của giáo dục phổ thông giai đoạn 2022-2030” và Công văn số 5162/BGDĐT-QLCL ngày 22/9/2023 của Bộ GDĐT về việc triển khai Đề án 468 ngày 13/02/2023; Ủy ban nhân dân (UBND) tỉnh ban hành Kế hoạch thực hiện Đề án trên địa bàn tỉnh Bà Rịa - Vũng Tàu với các nội dung sau:

I. MỤC TIÊU

1. Mục tiêu chung:

Tham gia đầy đủ các chương trình đánh giá diện rộng cấp quốc gia do Bộ Giáo dục và đào tạo tổ chức nhằm định kỳ cung cấp các thông tin khách quan, tin cậy về chất lượng giáo dục phổ thông, làm cơ sở đề xuất các chính sách, giải pháp đổi mới các hoạt động dạy và học đáp ứng yêu cầu triển khai Chương trình giáo dục phổ thông 2018, nâng cao chất lượng giáo dục phổ thông và hội nhập quốc tế tại địa phương.

2. Mục tiêu cụ thể:

a) Mục tiêu cụ thể giai đoạn 2022-2026

- Tham gia (cung cấp dữ liệu chọn mẫu đánh giá) các chương trình đánh giá diện rộng cấp quốc gia do Bộ GDĐT tổ chức gồm:

+ Tham gia 02 đợt đánh giá định kỳ quốc gia cho các khối lớp và lĩnh vực học tập được lựa chọn phù hợp với yêu cầu của Chương trình giáo dục phổ thông 2018;

+ Tham gia 02 chu kỳ của Chương trình đánh giá học sinh quốc tế (PISA)[2];

+ Tham gia 01 chu kỳ của Chương trình đánh giá kết quả học tập của học sinh tiểu học các quốc gia khu vực Đông Nam Á (SEA-PLM)- Tham gia đầy đủ các chương trình bồi dưỡng tập huấn, nâng cao năng lực cho đội ngũ tham gia chương trình đánh giá diện rộng cấp quốc gia do Bộ Giáo dục và Đào tạo tổ chức. Cụ thể gồm:

+ 100% các cơ sở giáo dục được lựa chọn vào mẫu đánh giá tham gia đầy đủ các chương trình đánh giá diện rộng cấp quốc gia tương ứng theo mục tiêu và quy trình kỹ thuật của mỗi kỳ đánh giá theo quy định;

+ 50% cán bộ làm công tác khảo thí của Sở Giáo dục và Đào tạo được bồi dưỡng tập huấn nâng cao năng lực và được cấp chứng nhận về đánh giá diện rộng cấp quốc gia nhằm đáp ứng tốt yêu cầu tổ chức các kỳ đánh giá;

+ 50% cán bộ quản lý giáo dục và giáo viên ở các cơ sở giáo dục phổ thông tham gia đánh giá được bồi dưỡng và cấp chứng nhận hoàn thành chương trình bồi dưỡng về đánh giá diện rộng cấp quốc gia hằng năm.

b) Mục tiêu cụ thể giai đoạn 2027-2030

- Tham gia (cung cấp dữ liệu chọn mẫu đánh giá) các chương trình đánh giá diện rộng cấp quốc gia do Bộ Giáo dục và Đào tạo tổ chức gồm:

+ Tham gia 01 đợt đánh giá định kỳ quốc gia hằng năm cho các khối lớp và lĩnh vực học tập được lựa chọn phù hợp với yêu cầu của Chương trình giáo dục phổ thông 2018;

+ Tham gia 01 chu kỳ của Chương trình đánh giá học sinh quốc tế (PISA); tham gia 01 chu kỳ của Chương trình phân tích các hệ thống giáo dục (PASEC)+ Tham gia 01 chu kỳ của Chương trình đánh giá kết quả học tập của học sinh Tiểu học các quốc gia khu vực Đông Nam Á (SEA-PLM).

- Tham gia đầy đủ các chương trình bồi dưỡng tập huấn, nâng cao năng lực cho đội ngũ tham gia chương trình đánh giá diện rộng cấp quốc gia do Bộ GDĐT tổ chức.

+ 100% các cơ sở giáo dục được lựa chọn vào mẫu đánh giá tham gia đầy đủ các chương trình đánh giá diện rộng cấp quốc gia tương ứng theo mục tiêu và quy trình kỹ thuật của mỗi kỳ đánh giá theo quy định;

+ 100% cán bộ làm công tác khảo thí cấp Sở được bồi dưỡng tập huấn nâng cao năng lực và được cấp chứng nhận về đánh giá diện rộng cấp quốc gia nhằm đáp ứng tốt yêu cầu tổ chức các kỳ đánh giá;

+ 100% cán bộ quản lý và giáo viên ở các cơ sở giáo dục phổ thông tham gia đánh giá được bồi dưỡng và được cấp chứng nhận hoàn thành chương trình bồi dưỡng về đánh giá diện rộng cấp quốc gia hàng năm.

II. NHIỆM VỤ VÀ GIẢI PHÁP

1. Tổ chức triển khai và sử dụng kết quả đánh giá diện rộng cấp quốc gia

- Triển khai thành công các kỳ đánh giá diện rộng cấp quốc gia bảo đảm mục tiêu, yêu cầu, quy trình, minh bạch và khách quan; đối với từng chu kỳ đánh giá diện rộng cấp quốc gia PISA, TALIS, SEA- PLM, PASEC thực hiện theo quyết định về việc ban hành kế hoạch tổng thể tổ chức triển khai chương trình đánh giá; chương trình phân tích các hệ thống giáo dục và kế hoạch hằng năm của Bộ Giáo dục và Đào tạo;

- Cung cấp thông tin, dữ liệu và kết quả thu được từ các chương trình đánh giá diện rộng cấp quốc gia cho Bộ Giáo dục và Đào tạo. Trên cơ sở phân tích kết quả thu được từ các chương trình đánh giá diện rộng cấp quốc gia đề xuất đối với các cơ quan liên quan chính sách phát triển giáo dục, góp phần đổi mới các hoạt động dạy học và giáo dục nhằm cải tiến chất lượng giáo dục phổ thông tại địa phương.

2. Phát triển đội ngũ phục vụ công tác quản lý và triển khai đánh giá diện rộng cấp quốc gia

- Phát triển đội ngũ cán bộ cốt cán về đánh giá chất lượng giáo dục để trở thành lực lượng nòng cốt cho công tác quản lý và triển khai thực hiện các chương trình đánh giá diện rộng cấp quốc gia;

- Nâng cao năng lực về đánh giá chất lượng giáo dục cho đội ngũ cán bộ làm công tác Quản lý chất lượng và đánh giá các cấp theo tiêu chuẩn trong nước và quốc tế, bảo đảm có đủ số lượng và năng lực để thực hiện các kỳ đánh giá diện rộng cấp quốc gia;

- Tham dự đầy đủ các khóa tập huấn cho cán bộ quản lý, giáo viên các cơ sở GDĐT phổ thông về đánh giá kết quả học tập của học sinh để thực hiện các kỳ đánh giá diện rộng cấp quốc gia;

- Tăng cường công tác thông tin, truyền thông nâng cao nhận thức về vai trò và ý nghĩa của đánh giá diện rộng cấp quốc gia đáp ứng yêu cầu nâng cao chất lượng giáo dục và hội nhập quốc tế cho đội ngũ cán bộ quản lý, cán bộ làm công tác khảo thí và đội ngũ giáo viên, học sinh ở các cơ sở GD phổ thông.

3. Đẩy mạnh ứng dụng công nghệ thông tin trong đánh giá diện rộng cấp quốc gia

- Tăng cường ứng dụng công nghệ thông tin trong đánh giá diện rộng cấp quốc gia, từng bước chuyển đánh giá trên giấy sang đánh giá trên máy tính để bảo đảm tính chính xác, khách quan, phù hợp với yêu cầu quốc tế;

- Tăng cường sử dụng các phần mềm trong phân tích dữ liệu trên cơ sở ứng dụng các thành tựu mới về khoa học đo lường, đánh giá trong giáo dục.

III. KINH PHÍ VÀ THỜI GIAN THỰC HIỆN

1. Kinh phí thực hiện

Từ nguồn ngân sách của tỉnh đối với các nội dung, công việc do địa phương thực hiện (bao gồm cử người tham gia tập huấn do Bộ Giáo dục và Đào tạo triệu tập, công tác tổ chức khảo sát theo hướng dẫn của Bộ Giáo dục và Đào tạo).

2. Thời gian thực hiện

Số lượng các đơn vị tham gia đánh giá trên diện rộng cấp quốc gia, quốc tế và thời gian thực hiện cụ thể theo kế hoạch của Bộ Giáo dục và Đào tạo.

IV. TỔ CHỨC THỰC HIỆN

1. Sở Giáo dục và Đào tạo

- Chủ trì triển khai các nhiệm vụ theo kế hoạch của Bộ Giáo dục và Đào tạo;

- Chỉ đạo, hướng dẫn các phòng Giáo dục và Đào tạo và các trường THPT xây dựng kế hoạch chi tiết để thực hiện các nhiệm vụ phù hợp với đặc điểm, tình hình địa phương, đơn vị; chuẩn bị đầy đủ các điều kiện cho việc đánh giá diện rộng cấp quốc gia;

- Theo dõi, đôn đốc, kiểm tra, báo cáo kết quả triển khai thực hiện kế hoạch theo yêu cầu của Bộ Giáo dục và Đào tạo và UBND tỉnh;

- Khai thác dữ liệu và kết quả của các kỳ khảo sát đánh giá diện rộng cấp quốc gia để tham mưu đề xuất chính sách, giải pháp cho giáo dục địa phương;

- Phối hợp với các cơ quan truyền thông nâng cao nhận thức về vai trò, ý nghĩa của chương trình đánh giá diện rộng quốc gia cho cán bộ giáo viên, học sinh và người dân biết để thực hiện;

- Phối hợp với Sở Tài chính lập dự toán kinh phí hằng năm đảm bảo nhiệm vụ chi cho công tác thực hiện kế hoạch; tham mưu bố trí nguồn kinh phí thực hiện từ ngân sách của tỉnh theo đúng quy định;

2. Sở Tài chính

Thẩm định dự toán chi tiết do Sở Giáo dục và Đào tạo lập, báo cáo Ủy ban nhân dân tỉnh xem xét, phê duyệt để làm cơ sở trình cấp có thẩm quyền bố trí kinh phí thực hiện theo đúng quy định của Luật Ngân sách nhà nước, theo phân cấp ngân sách nhà nước hiện hành và phù hợp với khả năng cân đối của Ngân sách.

3. Sở Thông tin và Truyền thông

Phối hợp với Sở Giáo dục và Đào tạo chuẩn bị đầy đủ cơ sở vật chất để ứng dụng công nghệ thông tin trong đánh giá diện rộng cấp quốc gia, từng bước chuyển đánh giá trên giấy sang đánh giá trên máy tính.

4. UBND các huyện, thị xã, thành phố

Chỉ đạo các đơn vị trực thuộc, các phòng Giáo dục và Đào tạo, các nhà trường xây dựng kế hoạch chi tiết để thực hiện các nhiệm vụ của Đề án phù hợp với đặc điểm tình hình kinh tế-xã hội địa phương, đơn vị; bố trí nguồn kinh phí thực hiện theo phân cấp ngân sách; kiểm tra, giám sát, đánh giá, tổng hợp kết quả thực hiện Kế hoạch tại địa phương, hàng năm báo cáo kết quả thực hiện về Sở Giáo dục và Đào tạo để tổng hợp báo cáo UBND tỉnh.

Trên đây là kế hoạch thực hiện Đề án “Phát triển hệ thống đánh giá diện rộng cấp quốc gia đáp ứng yêu cầu nâng cao chất lượng và hội nhập quốc tế của giáo dục phổ thông giai đoạn 2022-2030”, yêu cầu các cơ quan, đơn vị, địa phương chủ động phối hợp tổ chức thực hiện. Trong quá trình triển khai thực hiện, nếu có khó khăn, vướng mắc các cơ quan, đơn vị, địa phương kịp thời phản ánh, kiến nghị về Sở GDĐT để tổng hợp, báo cáo UBND tỉnh xem xét, chỉ đạo giải quyết./.

 


Nơi nhận:
- Bộ GDĐT (b/c);
- Chủ tịch UBND tỉnh (b/c);
- Sở GDĐT (t/h);
- Các Sở, Ban, ngành (t/h);
- UBND các huyện, thị xã, thành phố;
- VP UBND tỉnh;
- Lưu: VT, VX.

KT. CHỦ TỊCH
PHÓ CHỦ TỊCH




Đặng Minh Thông

 



lồng nhau (bên trong) hay không const memberID = 0; const vbID = '78b3810f92b33de12ab97de0ef48a682'; // State management cho phân tích let isAnalyzing = false; // Có đang phân tích không let currentAnalyzingAddress = null; // Address đang được phân tích let currentAnalyzingElement = null; // Element đang được phân tích let currentAnalyzingBadge = null; // Badge của element đang phân tích let isPanelOpen = false; // Panel phân tích có đang mở không console.log('Tiện ích loaded - memberID:', memberID, 'vbID:', vbID); function isInViewportAndTabNoiDung(element) { const rect = element.getBoundingClientRect(); const buffer = 1500; // Buffer to preload content below the viewport (approx. 50+ lines) const viewHeight = window.innerHeight || document.documentElement.clientHeight; const isInViewport = rect.top < viewHeight + buffer && rect.bottom >= 0; const isInTabNoiDung = $(element).closest('#tab_noi_dung_vb').length > 0; return isInViewport && isInTabNoiDung; } function getAddress(element) { const validTags = ['trichyeu', 'cancu', 'phan', 'chuong', 'muc', 'tieumuc', 'dieu', 'khoan', 'diem']; const $parent = $(element).closest(validTags.join(',')); if (!$parent.length) { return null; } let addr = $parent.attr('address'); if (!addr && $parent.prop('tagName').toLowerCase() === 'trichyeu') { addr = 'trichyeu'; $parent.attr('address', addr); } return addr || null; } function processTnplClasses($element) { const tnplKeysInLine = new Set(); // key = slug hoặc text (thường là slug) $element.find('tnpl').each(function () { const $tnpl = $(this); const tnplSlug = ($tnpl.attr('slug') || '').trim().toLowerCase(); const tnplKey = tnplSlug || $tnpl.text().trim().toLowerCase(); // Đã xử lý trong cùng dòng => bỏ if (tnplKeysInLine.has(tnplKey)) { return; } tnplKeysInLine.add(tnplKey); let tnplExists = false; // Chỉ duyệt các tnpl đã được tô màu (class on) $('tnpl.on').each(function () { const $existingTnpl = $(this); const existingSlug = ($existingTnpl.attr('slug') || '').trim().toLowerCase(); const existingKey = existingSlug || $existingTnpl.text().trim().toLowerCase(); if ( existingKey === tnplKey && isInViewportAndTabNoiDung($existingTnpl[0]) ) { tnplExists = true; return false; // break each } }); if (!tnplExists) { $tnpl.addClass('on'); } }); } function processQueue() { while (pendingRequests < maxConcurrentRequests && requestQueue.length > 0) { const task = requestQueue.shift(); pendingRequests++; task() .always(() => { pendingRequests--; processQueue(); }); } } function processVisibleParagraphs() { try { $('#tab_noi_dung_vb p:not([is-posted="1"])').each(function () { let $element = $(this); if (isInViewportAndTabNoiDung(this)) { $element.attr('is-posted', '1'); $element.addClass('loading-content'); let p_innerHTML = $element.html(); let address = null; if (cac_cau_hinh.loai_noi_dung.includes('docs')) { address = getAddress($element); } const isSubP = $element.parents('p').length > 0; if (isSubP && !allow_sub_p) { $element.removeClass('loading-content'); return; // Không gửi nếu không cho phép } const postData = { p_content: p_innerHTML, cac_cau_hinh, address }; if (isSubP && allow_sub_p) { postData.sub_p = 1; } requestQueue.push(() => $.ajax({ url: '//tnpl' + (Math.floor(Math.random() * 10) + 1) + '.hethongphapluat.com/tien-ich/tim.tien.ich.php', type: 'POST', data: postData, success: function(response) { $element.html(response); processTnplClasses($element); // Đợi CTTD và các tiện ích load xong rồi mới attach badge if (memberID === 4 && typeof attachPhanTichBadge === 'function') { setTimeout(function() { // $element chính là thẻ p, kiểm tra và attach badge trực tiếp const $parent = $element.closest('phan, chuong, muc, tieumuc, dieu, khoan, diem'); if ($parent.length > 0 && $parent.find('.badge-phan-tich[data-for="' + $parent.attr('address') + '"]').length === 0) { const address = $parent.attr('address'); $element.attr('data-address', address); // Lấy tên loại thẻ cho tooltip const parentType = getParentTypeName($parent.prop('tagName').toLowerCase()); // Append badge VÀO PARENT (dieu, khoan,...) thay vì vào

để tránh xung đột CTTD const $badge = $('Phân tích'); $parent.append($badge); // Thêm class để CSS set position: relative CHỈ cho element có badge $parent.addClass('has-phan-tich-badge'); } // Xử lý các p con (nếu có sub-p) attachPhanTichBadge($element); }, 300); // Đợi 300ms để CTTD render xong } }, complete: function() { $element.removeClass('loading-content'); } }) ); processQueue(); } }); } catch(e) { console.error('Lỗi processVisibleParagraphs:', e); } } $(window).on('scroll resize', function () { processVisibleParagraphs(); }); console.log('Bắt đầu processVisibleParagraphs lần đầu...'); processVisibleParagraphs(); console.log('processVisibleParagraphs lần đầu hoàn thành'); // Chức năng phân tích điều luật (chỉ cho member_id = 4) if (memberID === 4) { // Modal cảnh báo function showWarningModal(message) { // Tạo modal nếu chưa có if ($('#warningModal').length === 0) { const modalHTML = `

`; $('body').append(modalHTML); } $('#warningModalBody').html('

' + message + '

'); $('#warningModal').modal('show'); } // Hàm lấy tên tiếng Việt của thẻ function getParentTypeName(tagName) { const typeNames = { 'phan': 'Phần', 'chuong': 'Chương', 'muc': 'Mục', 'tieumuc': 'Tiểu mục', 'dieu': 'Điều', 'khoan': 'Khoản', 'diem': 'Điểm' }; return typeNames[tagName] || 'Nội dung'; } function attachPhanTichBadge($container) { const validTags = 'phan, chuong, muc, tieumuc, dieu, khoan, diem'; $container.find('p').each(function() { const $p = $(this); const $parent = $p.closest(validTags); if ($parent.length > 0) { const address = $parent.attr('address'); // Kiểm tra đã có badge cho parent này chưa if ($parent.find('.badge-phan-tich[data-for="' + address + '"]').length === 0) { // Lưu address vào data attribute $p.attr('data-address', address); // Lấy tên loại thẻ cho tooltip const parentType = getParentTypeName($parent.prop('tagName').toLowerCase()); // Append badge vào PARENT, không vào

const $badge = $('Phân tích'); $parent.append($badge); // Thêm class để CSS set position: relative CHỈ cho element có badge $parent.addClass('has-phan-tich-badge'); } } }); } // Helper: Escape HTML entities function escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return String(text).replace(/[&<>"']/g, function(m) { return map[m]; }); } // Helper: Convert Markdown to HTML (đơn giản) function markdownToHtml(markdown) { if (!markdown) return ''; let html = markdown; // Headers html = html.replace(/^### (.*$)/gim, '

$1
'); html = html.replace(/^## (.*$)/gim, '

$1

'); html = html.replace(/^# (.*$)/gim, '

$1

'); // Bold html = html.replace(/\*\*(.*?)\*\*/g, '$1'); // Italic html = html.replace(/\*(.*?)\*/g, '$1'); // Blockquote html = html.replace(/^> (.*$)/gim, '
$1
'); html = html.replace(/^> (.*$)/gim, '
$1
'); // Lists (unordered) html = html.replace(/^\- (.*$)/gim, '
  • $1
  • '); html = html.replace(/(
  • .*<\/li>)/s, '
      $1
    '); // Lists (ordered) html = html.replace(/^\d+\. (.*$)/gim, '
  • $1
  • '); // Line breaks và paragraphs html = html.split('\n\n').map(para => { para = para.trim(); if (para.startsWith('')) { return para; } if (para) { return '

    ' + para.replace(/\n/g, '
    ') + '

    '; } return ''; }).join('\n'); // Clean up multiple line breaks html = html.replace(/\n{3,}/g, '\n\n'); return html; } // Panel trượt đè lên #rightdocinfo để hiển thị phân tích điều luật function closePhanTichPanel() { const $panel = $('#phanTichPanel'); if ($panel.length) { $panel.removeClass('show'); setTimeout(() => $panel.remove(), 300); } // Reset highlight và badge khi đóng panel if (currentAnalyzingElement) { currentAnalyzingElement.removeClass('highlight-border-persistent'); } if (currentAnalyzingBadge) { currentAnalyzingBadge.text('Phân tích').removeClass('analyzing'); currentAnalyzingBadge.data('analyzing', false); currentAnalyzingBadge.data('hovering', false); currentAnalyzingBadge.css({display: 'none'}); // Ẩn badge khi đóng } // Reset tất cả các element khác (trong trường hợp có nhiều) $('#tab_noi_dung_vb .highlight-border-persistent').removeClass('highlight-border-persistent'); $('#tab_noi_dung_vb .badge-phan-tich-container.analyzing').each(function() { $(this).text('Phân tích').removeClass('analyzing').data('analyzing', false); }); // Reset state isAnalyzing = false; currentAnalyzingAddress = null; currentAnalyzingElement = null; currentAnalyzingBadge = null; isPanelOpen = false; // Đánh dấu panel đã đóng console.log('Panel closed, state reset, isPanelOpen = false'); } // Ngăn ẩn #rightdocinfo nếu panel phân tích đang mở - dùng MutationObserver const $rightdocinfo = $('#rightdocinfo'); if ($rightdocinfo.length > 0) { const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'attributes' && mutation.attributeName === 'style') { const $panel = $('#phanTichPanel'); const $container = $('#rightdocinfo'); // Nếu panel đang mở (dùng flag isPanelOpen) và rightdocinfo bị ẩn → show lại if (isPanelOpen && $panel.length > 0 && $panel.hasClass('show') && !$container.is(':visible')) { console.warn('⚠️ rightdocinfo was hidden but panel is open, forcing show'); $container.show(); } } }); }); observer.observe($rightdocinfo[0], { attributes: true, attributeFilter: ['style'] }); console.log('✅ MutationObserver set up to protect rightdocinfo when panel is open'); } // Backup: Check định kỳ setInterval(function() { const $panel = $('#phanTichPanel'); const $container = $('#rightdocinfo'); // Nếu panel đang hiển thị (dùng flag) và container bị ẩn → show lại if (isPanelOpen && $panel.length > 0 && $panel.hasClass('show') && !$container.is(':visible')) { console.log('⚠️ Panel is open but rightdocinfo is hidden, showing it'); $container.show(); } }, 500); // Check mỗi 500ms function openPhanTichPanel(address, vbID) { console.log('openPhanTichPanel called with address:', address); console.log('Current state - isAnalyzing:', isAnalyzing, 'currentAnalyzingAddress:', currentAnalyzingAddress); // Kiểm tra nếu đang phân tích element khác if (isAnalyzing && currentAnalyzingAddress && currentAnalyzingAddress !== address) { const currentName = getElementDisplayName(currentAnalyzingAddress); console.warn('Already analyzing:', currentAnalyzingAddress, 'Cannot analyze:', address); showWarningModal('Vui lòng chờ phân tích ' + currentName + ' hoàn tất...'); return; } // Nếu đang phân tích cùng element → không làm gì if (isAnalyzing && currentAnalyzingAddress === address) { console.log('Already analyzing this element, ignoring duplicate request'); return; } const $container = $('#rightdocinfo'); if ($container.length === 0) { // Fallback: nếu không có rightdocinfo, dùng modal cũ return openPhanTichModal(address, vbID); } // Đảm bảo #rightdocinfo đang hiển thị (có thể bị ẩn bởi CTTD pointer) if ($container.css('display') === 'none' || !$container.is(':visible')) { console.log('rightdocinfo is hidden, showing it for panel'); $container.show(); } // XÓA highlight persistent của TẤT CẢ elements cũ trước $('#tab_noi_dung_vb .highlight-border-persistent').removeClass('highlight-border-persistent'); console.log('Removed all previous highlight-border-persistent'); // Tìm element đang được phân tích và badge của nó const $element = $('[address="' + address + '"]'); const $badge = $element.find('.badge-phan-tich-container[data-for="' + address + '"]').first(); // Set state isAnalyzing = true; currentAnalyzingAddress = address; currentAnalyzingElement = $element; currentAnalyzingBadge = $badge; console.log('State set:', { isAnalyzing: isAnalyzing, currentAnalyzingAddress: currentAnalyzingAddress, elementFound: $element.length > 0, badgeFound: $badge.length > 0 }); // Thêm highlight persistent cho element MỚI này $element.addClass('highlight-border-persistent'); // Thay đổi badge thành "Đang phân tích..." và giữ hiển thị if ($badge.length > 0) { $badge.text('Đang phân tích...').addClass('analyzing'); // Giữ badge hiển thị và ở đúng vị trí $badge.data('analyzing', true); $badge.data('hovering', true); // Prevent auto-hide console.log('Badge set to analyzing state'); // Đảm bảo badge hiển thị ở đúng vị trí (vì dùng position: fixed) showPhanTichBadgeForParent($element); } // Tạo panel nếu chưa có if ($('#phanTichPanel').length === 0) { const panelHTML = `
    Phân tích điều luật
    Đang phân tích...

    Đang phân tích...

    `; // Đảm bảo container có position relative if ($container.css('position') === 'static') { $container.css('position', 'relative'); } $container.append(panelHTML); // Trigger slide-in và set flag setTimeout(() => { $('#phanTichPanel').addClass('show'); isPanelOpen = true; console.log('Panel opened, isPanelOpen = true'); }, 10); } else { $('#phanTichPanelBody').html(`
    Đang phân tích...

    Đang phân tích...

    `); $('#phanTichPanel').addClass('show'); isPanelOpen = true; console.log('Panel re-opened, isPanelOpen = true'); } // Bind nút đóng và ESC $(document).off('click.closePhanTich').on('click.closePhanTich', '.close-phan-tich', function() { closePhanTichPanel(); }); $(document).off('keyup.closePhanTich').on('keyup.closePhanTich', function(e) { if (e.key === 'Escape') closePhanTichPanel(); }); // Gọi API phân tích const randomServer = Math.floor(Math.random() * 10) + 1; $.ajax({ url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/phan.tich.dieu.luat.php', type: 'POST', contentType: 'application/json', timeout: 300000, // 5 phút data: JSON.stringify({ address: address, vb_id: vbID }), success: function(response) { console.log('Analysis complete for:', address, response); // Reset badge về trạng thái bình thường (nhưng vẫn hiển thị) if (currentAnalyzingBadge) { currentAnalyzingBadge.text('Phân tích').removeClass('analyzing'); currentAnalyzingBadge.data('analyzing', false); console.log('Badge reset to normal state'); } // Reset state analyzing để có thể phân tích element khác isAnalyzing = false; console.log('State reset: isAnalyzing = false, can analyze other elements now'); if (response.ok) { // Render kết quả phân tích let html = ''; html += '
    '; html += '
    ' + escapeHtml(response.ten_van_ban) + '
    '; if (response.so_hieu) { html += 'Số hiệu: ' + escapeHtml(response.so_hieu) + '
    '; } html += 'Điều khoản: ' + escapeHtml(response.address) + ''; html += '
    '; html += '
    ' + markdownToHtml(response.phan_tich) + '
    '; if (response.usage) { html += '
    '; html += 'Thống kê: '; html += 'Input tokens: ' + (response.usage.promptTokenCount || 0) + ', '; html += 'Output tokens: ' + (response.usage.candidatesTokenCount || 0); html += '
    '; } $('#phanTichPanelBody').html(html); } else { $('#phanTichPanelBody').html(` `); } }, error: function(xhr, status, error) { console.error('Analysis error:', error); // Reset badge về trạng thái bình thường if (currentAnalyzingBadge) { currentAnalyzingBadge.text('Phân tích').removeClass('analyzing'); currentAnalyzingBadge.data('analyzing', false); } // Reset state analyzing isAnalyzing = false; let errorMsg = error; if (xhr.responseJSON && xhr.responseJSON.error) { errorMsg = xhr.responseJSON.error; } $('#phanTichPanelBody').html(` `); } }); } // Helper: Lấy tên hiển thị của element từ address function getElementDisplayName(address) { if (!address) return 'nội dung'; const $element = $('[address="' + address + '"]'); if ($element.length === 0) return address; const tagName = $element.prop('tagName').toLowerCase(); const parentType = getParentTypeName(tagName); // Lấy số thứ tự từ address let displayText = parentType; // Parse address: vd "khoan_3_dieu_4" -> "Khoản 3 Điều 4" const parts = address.split('_'); for (let i = 0; i < parts.length; i += 2) { if (i + 1 < parts.length) { const type = getParentTypeName(parts[i]); const num = parts[i + 1]; displayText = type + ' ' + num; } } return displayText; } function openPhanTichModal(address, vbID) { // Tạo modal nếu chưa có if ($('#modalPhanTich').length === 0) { const modalHTML = ` `; $('body').append(modalHTML); } // Reset và hiển thị modal với loading $('#modalPhanTichBody').html(`
    Đang phân tích...

    Đang phân tích...

    `); $('#modalPhanTich').modal('show'); // AJAX request const randomServer = Math.floor(Math.random() * 10) + 1; $.ajax({ url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/phan.tich.dieu.luat.php', type: 'POST', contentType: 'application/json', data: JSON.stringify({ address: address, vb_id: vbID }), success: function(response) { if (response.ok) { // Render kết quả phân tích let html = ''; // Header thông tin văn bản html += '
    '; html += '
    ' + escapeHtml(response.ten_van_ban) + '
    '; if (response.so_hieu) { html += 'Số hiệu: ' + escapeHtml(response.so_hieu) + '
    '; } html += 'Điều khoản: ' + escapeHtml(response.address) + ''; html += '
    '; // Nội dung phân tích (Markdown -> HTML) html += '
    '; html += markdownToHtml(response.phan_tich); html += '
    '; // Thông tin usage (nếu có) if (response.usage) { html += '
    '; html += 'Thống kê: '; html += 'Input tokens: ' + (response.usage.promptTokenCount || 0) + ', '; html += 'Output tokens: ' + (response.usage.candidatesTokenCount || 0); html += '
    '; } $('#modalPhanTichBody').html(html); } else { $('#modalPhanTichBody').html(` `); } }, error: function(xhr, status, error) { let errorMsg = error; if (xhr.responseJSON && xhr.responseJSON.error) { errorMsg = xhr.responseJSON.error; } $('#modalPhanTichBody').html(` `); } }); } // Helpers: show/hide badge cho parent element (dieu, khoan,...) với position: fixed function showPhanTichBadgeForParent($parent) { // Lấy badge CỦA CHÍNH parent này (match data-for với address của parent) const parentAddress = $parent.attr('address'); const $badge = $parent.find('.badge-phan-tich-container[data-for="' + parentAddress + '"]').first(); if ($badge.length === 0) { console.warn('No badge found for parent:', parentAddress); return; } // Ẩn TẤT CẢ các badge khác để tránh overlap $('.badge-phan-tich-container').not($badge).each(function() { const $otherBadge = $(this); // Chỉ ẩn badge KHÔNG đang analyzing if (!$otherBadge.data('analyzing')) { $otherBadge.css({display: 'none'}); } }); // Show badge tạm để tính width $badge.css({display: 'inline-block', opacity: 0, visibility: 'hidden'}); const badgeWidth = $badge.outerWidth(); // Tính toán vị trí fixed dựa trên offset của parent const offset = $parent.offset(); const scrollTop = $(window).scrollTop(); const scrollLeft = $(window).scrollLeft(); // Position badge top-right của parent và show $badge.css({ display: 'inline-block', visibility: 'visible', opacity: 1, top: (offset.top - scrollTop) + 'px', left: (offset.left + $parent.outerWidth() - badgeWidth - scrollLeft - 5) + 'px' // -5px padding }); console.log('Showing badge for:', parentAddress, 'at position:', $badge.css('top'), $badge.css('left')); $parent.addClass('highlight-border'); } function hidePhanTichBadgeForParent($parent) { const $badge = $parent.find('.badge-phan-tich-container').first(); if ($badge.length === 0) return; $badge.css({display: 'none', opacity: 0}); $parent.removeClass('highlight-border'); } // Event delegation cho hover vào parent elements (dieu, khoan,...) - attach badge nếu chưa có, rồi show $(document).on('mouseenter', '#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem', function(e) { // Stop propagation để tránh highlight parent khi hover vào child e.stopPropagation(); const $parent = $(this); const address = $parent.attr('address'); // Set flag hovering $parent.data('hovering', true); // Cancel timeout nếu có const timeoutId = $parent.data('hideTimeout'); if (timeoutId) { clearTimeout(timeoutId); } // Ẩn highlight của tất cả parent elements khác (trừ element đang analyzing) $('#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem') .not($parent) .each(function() { const $el = $(this); // Chỉ xóa highlight-border, KHÔNG xóa highlight-border-persistent $el.removeClass('highlight-border'); // Ẩn badge nếu KHÔNG đang analyzing const $badge = $el.find('.badge-phan-tich-container'); if ($badge.length && !$badge.data('analyzing')) { $badge.css({display: 'none'}); } }); // Attach badge nếu chưa có - badge phải có data-for = address của PARENT, không phải child if (address && $parent.find('.badge-phan-tich-container[data-for="' + address + '"]').length === 0) { const parentType = getParentTypeName($parent.prop('tagName').toLowerCase()); // Tạo badge với data-for = address của PARENT element này const $badge = $('Phân tích'); console.log('Creating badge for address:', address, 'parentType:', parentType); $parent.append($badge); $parent.addClass('has-phan-tich-badge'); } // Show badge cho element này if ($parent.find('.badge-phan-tich-container').length > 0) { showPhanTichBadgeForParent($parent); } }); // Event delegation cho hover ra khỏi parent $(document).on('mouseleave', '#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem', function(e) { const $parent = $(this); const parentAddress = $parent.attr('address'); const $badge = $parent.find('.badge-phan-tich-container[data-for="' + parentAddress + '"]').first(); // Set flag parent not hovering $parent.data('hovering', false); // Nếu badge đang analyzing thì KHÔNG ẩn, GIỮ hiển thị if ($badge.length > 0 && $badge.data('analyzing')) { console.log('Badge is analyzing, keep visible'); return; } // Delay để có thời gian di chuột vào badge const timeoutId = setTimeout(() => { // Chỉ ẩn nếu cả parent và badge đều không hover và không analyzing if ($badge.length > 0 && !$parent.data('hovering') && !$badge.data('hovering') && !$badge.data('analyzing')) { hidePhanTichBadgeForParent($parent); } }, 300); // Tăng lên 300ms $parent.data('hideTimeout', timeoutId); }); // Hover vào badge → giữ hiển thị $(document).on('mouseenter', '.badge-phan-tich-container', function(e) { e.stopPropagation(); const $badge = $(this); const $parent = $badge.parent(); $badge.data('hovering', true); // Cancel timeout của parent const timeoutId = $parent.data('hideTimeout'); if (timeoutId) { clearTimeout(timeoutId); } }); // Hover ra khỏi badge → ẩn nếu không hover parent $(document).on('mouseleave', '.badge-phan-tich-container', function(e) { const $badge = $(this); $badge.data('hovering', false); const $parent = $badge.parent(); // Nếu badge đang analyzing thì KHÔNG ẩn, GIỮ hiển thị if ($badge.data('analyzing') || $badge.hasClass('analyzing')) { console.log('Badge is analyzing on mouseleave, keep visible'); return; } setTimeout(() => { // Chỉ ẩn nếu cả parent và badge đều không hover và không analyzing if (!$parent.data('hovering') && !$badge.data('hovering') && !$badge.data('analyzing') && !$badge.hasClass('analyzing')) { hidePhanTichBadgeForParent($parent); } }, 300); }); // Event delegation cho hover vào badge → hiện tooltip $(document).on('mouseenter', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function() { const $badge = $(this); const parentType = $badge.attr('data-parent-type') || 'Nội dung'; if ($badge.find('.badge-tooltip').length === 0) { const $tooltip = $('Phân tích chi tiết nội dung ' + parentType + ' này'); $badge.append($tooltip); setTimeout(() => $tooltip.addClass('show'), 10); } }); // Event delegation cho hover ra khỏi badge → ẩn tooltip $(document).on('mouseleave', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function() { const $tooltip = $(this).find('.badge-tooltip'); if ($tooltip.length > 0) { $tooltip.removeClass('show'); setTimeout(() => $tooltip.remove(), 300); } }); // Event delegation cho click badge → mở panel $(document).on('click', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function(e) { e.preventDefault(); e.stopPropagation(); const $badge = $(this); console.log('Badge clicked! Element:', $badge[0]); console.log('Badge parent:', $badge.parent().prop('tagName'), $badge.parent().attr('address')); console.log('Badge data-for:', $badge.attr('data-for')); console.log('Badge data-parent-type:', $badge.attr('data-parent-type')); // Nếu badge đang analyzing thì không cho click if ($badge.hasClass('analyzing') || $badge.data('analyzing')) { console.log('Badge is analyzing, click ignored'); return; } // Lấy address từ data-for attribute const address = $badge.attr('data-for'); console.log('Will analyze address:', address, 'vbID:', vbID); if (address && vbID) { openPhanTichPanel(address, vbID); } else { console.error('Missing address or vbID', {address, vbID}); showWarningModal('Không tìm thấy địa chỉ điều luật hoặc ID văn bản!'); } }); // Ẩn badge khi click vào CTTD để tránh xung đột UI $(document).on('click', 'cttd.chuthichtudong span, dctk span, dctd span', function(e) { console.log('CTTD clicked'); // Ẩn TẤT CẢ badge KHÔNG đang analyzing (không chỉ badge của parent) $('.badge-phan-tich-container').each(function() { const $badge = $(this); // Chỉ ẩn nếu KHÔNG đang analyzing if (!$badge.data('analyzing') && !$badge.hasClass('analyzing')) { $badge.css({display: 'none'}); console.log('Hiding badge:', $badge.attr('data-for')); } else { console.log('Keeping badge visible (analyzing):', $badge.attr('data-for')); // Đảm bảo badge analyzing vẫn visible và ở đúng vị trí const $parent = $badge.parent(); setTimeout(() => { if ($badge.data('analyzing') || $badge.hasClass('analyzing')) { showPhanTichBadgeForParent($parent); console.log('Re-showing analyzing badge after CTTD click'); } }, 100); } }); }); // Update badge position khi scroll hoặc resize (vì dùng position: fixed) function updateBadgePositions() { $('.badge-phan-tich-container:visible').each(function() { const $badge = $(this); const $parent = $badge.parent(); // Cập nhật position nếu parent đang hover HOẶC badge đang analyzing if ($parent.length && ($parent.is(':hover') || $badge.data('analyzing'))) { // Re-calculate position const offset = $parent.offset(); const scrollTop = $(window).scrollTop(); const scrollLeft = $(window).scrollLeft(); const badgeWidth = $badge.outerWidth(); $badge.css({ top: (offset.top - scrollTop) + 'px', left: (offset.left + $parent.outerWidth() - badgeWidth - scrollLeft - 5) + 'px' }); } }); } $(window).on('scroll', updateBadgePositions); $(window).on('resize', updateBadgePositions); } });