Hệ thống pháp luật

BAN CHẤP HÀNH TRUNG ƯƠNG
VĂN PHÒNG
-------

ĐẢNG CỘNG SẢN VIỆT NAM
---------------

Số: 15-HD/VPTW

Hà Nội, ngày 14 tháng 12 năm 2016

 

HƯỚNG DẪN

QUẢN LÝ TÀI LIỆU LƯU TRỮ CỦA CÁC CƠ QUAN, TỔ CHỨC ĐẢNG VÀ CÁC TỔ CHỨC CHÍNH TRỊ - XÃ HỘI XÃ, PHƯỜNG, THỊ TRẤN

Thực hiện Điều 14 của Luật Lưu trữĐiều 15 Quy định số 270-QĐ/TW, ngày 06-12-2014 của Ban Bí thư Trung ương Đảng về Phông Lưu trữ Đảng Cộng sản Việt Nam, Văn phòng Trung ương Đảng hướng dẫn về việc quản lý tài liệu lưu trữ của các cơ quan, tổ chức đảng và các tổ chức chính trị - xã hội xã, phường, thị trấn (sau đây gọi chung là cấp xã) như sau:

I- HƯỚNG DẪN CHUNG

1- Phạm vi và đối tượng áp dụng

Văn bản này hướng dẫn về nguyên tắc, nội dung, trách nhiệm quản lý tài liệu lưu trữ của các cơ quan, tổ chức đảng và các tổ chức chính trị - xã hội cấp xã.

2- Giải thích từ ngữ

- “Các cơ quan, tổ chức đảng và các tổ chức chính trị - xã hội cấp xã” bao gồm: Đảng ủy cấp xã; các ban tham mưu, giúp việc đảng ủy cấp xã (ủy ban kiểm tra, ban tổ chức, ban tuyên giáo, ban dân vận, văn phòng đảng ủy cấp xã); Mặt trận Tổ quốc cấp xã, hội liên hiệp phụ nữ cấp xã, hội nông dân cấp xã, hội cựu chiến binh cấp xã, đoàn thanh niên cấp xã.

- “Tài liệu lưu trữ của các cơ quan, tổ chức đảng và các tổ chức chính trị - xã hội cấp xã” là tài liệu có giá trị phục vụ hoạt động thực tiễn, nghiên cứu khoa học, lịch sử được lựa chọn từ toàn bộ khối tài liệu hình thành trong hoạt động của đảng ủy cấp xã, các ban tham mưu, giúp việc đảng ủy cấp xã, Mặt trận Tổ quốc cấp xã, hội liên hiệp phụ nữ cấp xã, hội nông dân cấp xã, hội cựu chiến binh cấp xã, đoàn thanh niên cấp xã qua các thời kỳ lịch sử.

Tài liệu lưu trữ bao gồm bản gốc, bản chính; trong trường hợp không còn bản gốc, bản chính thì được thay thế bằng bản sao hợp pháp.

- “Quản lý tài liệu lưu trữ” bao gồm việc thu thập, chỉnh lý, bảo quản và tổ chức sử dụng tài liệu lưu trữ.

3- Nguyên tắc quản lý tài liệu lưu trữ

Tài liệu lưu trữ hình thành trong quá trình hoạt động của các cơ quan, tổ chức đảng và các tổ chức chính trị - xã hội cấp xã được lựa chọn và quản lý tập trung tại văn phòng đảng ủy cấp xã4- Trách nhiệm quản lý tài liệu lưu trữ

- Bí thư đảng ủy cấp xã chịu trách nhiệm quản lý tài liệu lưu trữ hình thành trong hoạt động của đảng ủy và các tổ chức chính trị - xã hội cấp xã; chỉ đạo việc thực hiện các quy định của Đảng về công tác văn thư, lưu trữ tại địa phương.

- Cán bộ được giao làm công tác lưu trữ tại văn phòng đảng ủy cấp xã có trách nhiệm giúp bí thư đảng ủy cấp xã thực hiện các nhiệm vụ sau: Hướng dẫn cán bộ, công chức đảng ủy và các tổ chức chính trị - xã hội cấp xã lập hồ sơ công việc và giao nộp hồ sơ vào văn phòng đảng ủy cấp xã; tiếp nhận hồ sơ, tài liệu giao nộp; tổ chức chỉnh lý khoa học tài liệu lưu trữ; sắp xếp khoa học tài liệu trong kho lưu trữ, bảo quản an toàn tài liệu lưu trữ và tổ chức sử dụng có hiệu quả tài liệu lưu trữ.

- Cán bộ, công chức và những người hoạt động không chuyên trách ở đảng ủy cấp xã và các tổ chức chính trị - xã hội cấp xã trong quá trình theo dõi, giải quyết công việc có trách nhiệm lập hồ sơ và giao nộp hồ sơ, tài liệu vào văn phòng đảng ủy cấp xã theo quy định.

II- HƯỚNG DẪN CỤ THỂ

1- Thu thập hồ sơ, tài liệu vào văn phòng đảng ủy cấp xã

1.1- Thời hạn giao nộp hồ sơ, tài liệu vào văn phòng đảng ủy cấp xã

- Hồ sơ đại hội đảng bộ cấp xã: Trong thời hạn 1 tháng kể từ khi đại hội kết thúc.

- Quý I hằng năm, các bộ phận, cá nhân thuộc đảng ủy cấp xã giao nộp hồ sơ, tài liệu có giá trị lưu trữ đã giải quyết xong của năm trước vào văn phòng đảng ủy cấp xã. Riêng hồ sơ, tài liệu xây dựng cơ bản thì giao nộp vào lưu trữ văn phòng đảng ủy cấp xã trong thời hạn 3 tháng, kể từ ngày công trình được quyết toán. Trường hợp bộ phận, cá nhân có nhu cầu giữ lại hồ sơ, tài liệu đã đến hạn nộp lưu theo quy định để phục vụ công việc phải lập danh mục hồ sơ, tài liệu giữ lại gửi cho lưu trữ văn phòng đảng ủy cấp xã. Thời hạn giữ lại hồ sơ, tài liệu của bộ phận, cá nhân không quá 2 năm, kể từ ngày đến hạn nộp lưu.

- Các đảng ủy bộ phận (nếu có), chi ủy trực thuộc đảng ủy cấp xã; Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã giao nộp hồ sơ, tài liệu vào văn phòng đảng ủy cấp xã sau khi kết thúc nhiệm kỳ hoạt động, thời gian không quá 3 tháng.

1.2- Thủ tục giao nộp và tiếp nhận hồ sơ, tài liệu

- Văn phòng đảng ủy cấp xã chuẩn bị đầy đủ các điều kiện cơ sở vật chất cần thiết để bảo quản hồ sơ, tài liệu khi tiếp nhận về.

- Ngay sau khi kết thúc nhiệm kỳ hoạt động, đảng ủy, chi ủy trực thuộc đảng ủy cấp xã; Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã chuẩn bị hồ sơ, tài liệu theo đúng tiêu chuẩn để giao nộp vào văn phòng đảng ủy cấp xã.

- Khi tiếp nhận hồ sơ, tài liệu, bên giao và bên nhận có trách nhiệm kiểm tra, đối chiếu thực tế hồ sơ, tài liệu giao nộp với thực tế mục lục hồ sơ, mục lục tài liệu giao nộp. Cán bộ làm công tác lưu trữ tại văn phòng đảng ủy cấp xã lập biên bản giao nhận hồ sơ, tài liệu. Biên bản được làm thành hai bản có chữ ký của người giao, người nhận và xác nhận của bí thư đảng ủy cấp xã, bên giao giữ 1 bản, bên nhận giữ 1 bản.

- Sau mỗi đợt tiếp nhận hồ sơ, tài liệu, cán bộ làm công tác lưu trữ tại văn phòng đảng ủy cấp xã có trách nhiệm làm báo cáo kết quả giao nộp hồ sơ, tài liệu gửi thường trực đảng ủy cấp xã.

1.3- Nguồn nộp lưu tài liệu lưu trữ vào văn phòng đảng ủy cấp xã

- Các cơ quan lãnh đạo đảng ở cấp xã:

Đại hội đảng bộ cấp xã.

Ban chấp hành đảng bộ cấp xã.

- Các ban tham mưu, giúp việc đảng ủy cấp xã:

Ủy ban kiểm tra.

Văn phòng.

Ban tổ chức.

Ban tuyên giáo.

Ban dân vận.

- Các đảng ủy, chi ủy trực thuộc đảng ủy cấp xã.

- Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã:

Mặt trận Tổ quốc.

Công đoàn.

Hội liên hiệp phụ nữ.

Hội cựu chiến binh.

Hội nông dân.

Đoàn thanh niên.

1.4- Thành phần tài liệu lưu trữ giao nộp vào văn phòng đảng ủy cấp xã

- Tài liệu đại hội đảng bộ cấp xã.

- Tài liệu hình thành trong quá trình hoạt động của đảng ủy cấp xã: Tài liệu hội nghị ban chấp hành, ban thường vụ, hội nghị cán bộ; tài liệu do đảng ủy cấp xã ban hành; tài liệu của thường trực đảng ủy cấp xã; tài liệu của các cơ quan cấp trên và của các cơ quan, tổ chức, cá nhân khác gửi đến.

- Tài liệu của Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã: Tài liệu đại hội và tài liệu hình thành trong quá trình hoạt động của Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã.

- Tài liệu của các đảng ủy, chi ủy trực thuộc đảng ủy cấp xã: Đại hội, tài liệu hình thành trong quá trình hoạt động của các đảng ủy, chi ủy.

- Hồ sơ đảng viên nghỉ hưu và từ trần; hồ sơ cán bộ, công chức đã từ trần.

2- Chỉnh lý, xác định giá trị tài liệu

- Cán bộ làm công tác lưu trữ tại văn phòng đảng ủy cấp xã trực tiếp kiểm tra các hồ sơ do các đảng ủy, chi ủy trực thuộc, Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã giao nộp; viết bìa hồ sơ; sắp xếp hồ sơ, tài liệu vào hộp (cặp), ghi và dán nhãn hộp (cặp), đưa lên giá.

- Tài liệu đại hội đảng bộ cấp xã, tài liệu hình thành trong quá trình hoạt động của ban chấp hành, ban thường vụ đảng ủy cấp xã, tài liệu hình thành trong quá trình hoạt động của văn phòng và các ban tham mưu, giúp việc đảng ủy cấp xã sau khi thu về cần phải được tổ chức chỉnh lý hoàn chỉnh. Tài liệu sau khi chỉnh lý phải bảo đảm các yêu cầu cơ bản sau đây: Được xác định giá trị tài liệu, phân loại theo nguyên tắc nghiệp vụ lưu trữ; được xác định thời hạn bảo quản; hồ sơ được hoàn thiện và hệ thống hoá; có mục lục hồ sơ, cơ sở dữ liệu tài liệu lưu trữ và danh mục tài liệu hết giá trị (việc xác định giá trị tài liệu lưu trữ thực hiện theo hướng dẫn của Văn phòng Trung ương Đảng).

3- Thống kê, bảo quản và tổ chức khai thác, sử dụng tài liệu lưu trữ

3.1- Chế độ báo cáo thống kê, kiểm kê

3.1.1- Chế độ báo cáo thống kê

- Hằng năm, cán bộ làm công tác lưu trữ tại văn phòng đảng ủy cấp xã phải thực hiện thống kê định kỳ về công tác văn thư, công tác lưu trữ và tài liệu lưu trữ, gửi văn phòng cấp ủy huyện để tổng hợp.

- Số liệu thống kê lưu trữ định kỳ hằng năm được tính từ 0 giờ, ngày 01-01 đến 24 giờ, ngày 31-12 (theo mẫu biểu tại Hướng dẫn số 38-HD/VPTW, ngày 23-9-2014 của Văn phòng Trung ương Đảng).

3.1.2- Chế độ kiểm kê định kỳ

Cán bộ làm công tác lưu trữ tại văn phòng đảng ủy cấp xã phải tổ chức kiểm kê tài liệu lưu trữ theo định kỳ mỗi năm một lần vào ngày 31-12 hằng năm.

3.2- Bảo quản tài liệu lưu trữ

- Tài liệu lưu trữ của các cơ quan, tổ chức đảng, Mặt trận Tổ quốc và các tổ chức chính trị - xã hội cấp xã phải được bảo vệ, bảo quản an toàn trong phòng, kho lưu trữ.

- Phòng, kho bảo quản tài liệu lưu trữ phải đáp ứng các điều kiện về bảo vệ, bảo quản an toàn tài liệu và thông tin tài liệu lưu trữ.

Phòng, kho bảo quản tài liệu lưu trữ phải được bố trí độc lập trong trụ sở đảng ủy xã với diện tích tối thiểu 20 m2.

Vị trí phòng, kho bảo quản tránh nơi ẩm thấp hoặc chịu tác động trực tiếp của ánh sáng mặt trời.

Phòng, kho bảo quản phải bảo đảm sạch sẽ và có trang bị quạt thông gió.

Kho phải có đủ giá (kệ), bài, hộp, cặp bảo quản hồ sơ, tài liệu.

Trang bị đủ các phương tiện, thiết bị phòng cháy, chữa cháy.

- Phải thực hiện chế độ vệ sinh kho; thực hiện và duy trì các biện pháp chống côn trùng phá hoại tài liệu.

3.3- Tổ chức khai thác, sử dụng tài liệu lưu trữ

- Tài liệu lưu trữ được bảo quản tại kho lưu trữ văn phòng đảng ủy xã được sử dụng để phục vụ nhu cầu công tác của cán bộ, công chức cấp xã và các nhu cầu chính đáng của cơ quan, tổ chức, cá nhân. Cán bộ làm công tác lưu trữ tại văn phòng đảng ủy xã có trách nhiệm trực tiếp phục vụ các nhu cầu khai thác, sử dụng tài liệu.

- Bí thư đảng ủy xã ban hành quy định về việc sử dụng tài liệu lưu trữ tại kho lưu trữ văn phòng đảng ủy xã.

- Đơn vị, cá nhân khi sử dụng tài liệu lưu trữ phải chấp hành nghiêm chỉnh các quy định về bảo mật thông tin và giữ gìn bảo đảm an toàn tài liệu.

III- TỔ CHỨC THỰC HIỆN

- Các văn phòng tỉnh ủy, thành ủy có trách nhiệm triển khai Hướng dẫn này đến các huyện, quận, thị, thành ủy trực thuộc tỉnh ủy, thành ủy và các đảng ủy xã, phường, thị trấn.

- Giao Cục Lưu trữ Văn phòng Trung ương Đảng theo dõi, đôn đốc và kiểm tra việc thực hiện Hướng dẫn này.

- Trong quá trình thực hiện nếu có vướng mắc, đề nghị các cơ quan phản ánh về Văn phòng Trung ương Đảng để nghiên cứu, điều chỉnh cho phù hợp.

 


Nơi nhận:
- Các văn phòng tỉnh ủy, thành ủy,
- Cục Lưu trữ,
- Lưu Văn phòng Trung ương Đảng.

K/T CHÁNH VĂN PHÒNG
PHÓ CHÁNH VĂN PHÒNG




Bùi Văn Thạch

 



lồng nhau (bên trong) hay không const memberID = 0; const vbID = 'b8deb3a4567d94f5c6a7e066e2099320'; // 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 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; } 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; } // ĐÓNG tất cả CTTD pointer đang mở để tránh xung đột z-index const $cttdPointers = $('.pointer.pointy.zindex'); const $cttdCanvas = $('canvas.pointy.zindex'); if ($cttdPointers.length > 0 || $cttdCanvas.length > 0) { console.log('Found CTTD pointers:', $cttdPointers.length, 'canvas:', $cttdCanvas.length, '- closing...'); $('.close_pointy').trigger('click'); // Đóng trực tiếp nếu còn $cttdPointers.fadeOut(200, function() { $(this).remove(); }); $cttdCanvas.fadeOut(200, function() { $(this).remove(); }); console.log('CTTD pointers and canvas removed'); } const $container = $('#rightdocinfo'); if ($container.length === 0) { // Fallback: nếu không có rightdocinfo, dùng modal cũ return openPhanTichModal(address, vbID); } // 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ới force z-index setTimeout(() => { const $panel = $('#phanTichPanel'); $panel.addClass('show'); $panel.css('z-index', '10001'); // Force z-index console.log('Panel created and shown with z-index:', $panel.css('z-index')); }, 10); } else { $('#phanTichPanelBody').html(`
    Đang phân tích...

    Đang phân tích...

    `); const $panel = $('#phanTichPanel'); $panel.addClass('show'); $panel.css('z-index', '10001'); // Force z-index console.log('Panel re-shown with z-index:', $panel.css('z-index')); } // 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); } });