ỦY BAN NHÂN DÂN THÀNH PHỐ HÀ NỘI -------
CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc lập - Tự do - Hạnh phúc ---------------
Số: 256/KH-UBND
Hà Nội, ngày 24 tháng 10 năm 2023
KẾ HOẠCH
KIỂM TRA VIỆC TRIỂN KHAI THỰC HIỆN QUY ĐỊNH CỦA PHÁP LUẬT TRONG CÁC LĨNH VỰC CÓ LIÊN QUAN ĐẾN CÔNG TÁC PCCC VÀ CNCH TRÊN ĐỊA BÀN THÀNH PHỐ
Thực hiện Công điện số 796/CĐ-TTg ngày 13/9/2023, công điện 825/CĐ-TTg ngày 15/9/2023 của Thủ tướng Chính phủ về tăng cường công tác phòng cháy, chữa cháy; để kịp thời phát hiện, chấn chỉnh, khắc phục những tồn tại, thiếu sót, nâng cao hiệu quả công tác quản lý nhà nước trong các lĩnh vực có liên quan đến công tác PCCC và CNCH, UBND Thành phố ban hành Kế hoạch kiểm tra việc triển khai thực hiện quy định của pháp luật trong các lĩnh vực có liên quan công tác PCCC và CNCH trên địa bàn Thành phố, cụ thể như sau:
I. MỤC ĐÍCH, YÊU CẦU
1. Siết chặt kỷ luật, kỷ cương; nâng cao vai trò trách nhiệm trong lãnh đạo, chỉ đạo của người đứng đầu các cấp ủy Đảng, chính quyền địa phương, các ngành chức năng. Đánh giá đúng thực trạng việc thực hiện và công tác phối hợp trong quản lý nhà nước (QLNN) của các cơ quan quản lý; ý thức, nhận thức, trách nhiệm của người đứng đầu cơ sở, chủ hộ gia đình và người dân trong việc thực hiện quy định pháp luật của các lĩnh vực có liên quan đến công tác PCCC và CNCH.
2. Kiểm tra việc triển khai thực hiện quy định của pháp luật trong các lĩnh vực có liên quan công tác PCCC và CNCH tại một số đơn vị cấp huyện, cấp xã và tại cơ sở thuộc loại hình tập trung đông người, trọng điểm có nguy cơ cháy, nổ cao (chung cư, nhà ở nhiều căn hộ, cơ sở kinh doanh dịch vụ cho thuê trọ, nhà ở kết hợp kinh doanh, sản xuất...) trên địa bàn Thành phố.
3. Qua công tác kiểm tra, kịp thời phát hiện những tồn tại, hạn chế, yếu kém để xử lý nghiêm đối với các tập thể, cá nhân vi phạm, thiếu trách nhiệm trong thực hiện nhiệm vụ được giao; tổng hợp khó khăn, vướng mắc, bất cập trong quá trình triển khai thực hiện để kịp thời có các biện pháp, giải pháp sát hợp, căn cơ; kiến nghị đề xuất cấp có thẩm quyền các vấn đề bất cập, nhằm nâng cao hiệu lực, hiệu quả công tác QLNN trong các lĩnh vực liên quan đến PCCC và CNCH trong thời gian tới.
4. Việc kiểm tra phải đảm bảo tính khách quan, toàn diện, đánh giá đúng thực trạng tình hình, trách nhiệm của các tập thể, cơ sở, cá nhân trong thực hiện quy định của pháp luật liên quan đến công tác PCCC&CNCH; xử lý nghiêm tất cả hành vi vi phạm theo quy định của pháp luật. Quá trình kiểm tra không làm ảnh hưởng đến hoạt động của đơn vị, cơ sở được kiểm tra.
II. ĐỐI TƯỢNG, THỜI GIAN, HÌNH THỨC KIỂM TRA
1. Đối tượng kiểm tra: UBND cấp huyện, cấp xã; Công an cấp huyện, cấp xã; cơ sở tập trung đông người, cơ sở trọng điểm có nguy cơ cháy, nổ cao (chung cư, nhà ở nhiều căn hộ, cơ sở kinh doanh dịch vụ cho thuê trọ, nhà ở kết hợp kinh doanh, sản xuất,...) trên địa bàn Thành phố (do đồng chí Trưởng đoàn kiểm tra xem xét, quyết định).
2. Thời gian, địa điểm kiểm tra
2.1. Thời gian: Từ ngày 25/10/2023 đến ngày 15/12/2023.
2.2. Địa điểm: Làm việc trực tiếp tại đơn vị, cơ sở được lựa chọn kiểm tra.
3. Hình thức kiểm tra: Kiểm tra đột xuất theo kế hoạch.
III. NỘI DUNG KIỂM TRA
1. Kiểm tra việc quán triệt, chỉ đạo, tổ chức triển khai thực hiện Nghị Quyết, Chỉ thị, Kế hoạch, văn bản chỉ đạo của Thành ủy, HĐND Thành phố, UBND Thành phố đã ban hành trong thời gian vừa qua (2. Kiểm tra công tác quản lý nhà nước, công tác xử lý vi phạm (nếu có) của các cơ quan được giao nhiệm vụ quản lý; việc chấp hành quy định pháp luật về đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện, an toàn về PCCC và CNCH đối với một số cơ sở thuộc loại hình chung cư, nhà ở nhiều căn hộ, cơ sở kinh doanh dịch vụ cho thuê trọ, nhà ở kết hợp kinh doanh, sản xuất... trên địa bàn Thành phố.
3. Trường hợp phát hiện cơ sở có vi phạm quy định các lĩnh vực được kiểm tra, giao UBND cấp huyện chỉ đạo xử lý theo quy định; đồng thời đánh giá, làm rõ trách nhiệm công tác quản lý nhà nước của các cơ quan, tập thể, cá nhân có liên quan, đề xuất hình thức xử lý theo quy định.
IV. THÀNH PHẦN ĐOÀN KIỂM TRA
1. Đại diện lãnh đạo UBND Thành phố - Trưởng đoàn;
2. Đồng chí Đại tá Dương Đức Hải, Phó Giám đốc Công an Thành phố - Phó Trưởng đoàn Thường trực;
3. Đại diện lãnh đạo Văn phòng UBND Thành phố - Phó Trưởng đoàn;
4. Đại diện lãnh đạo và chuyên viên các Sở, ngành: Công Thương, Xây dựng, Quy hoạch - Kiến trúc, Tài nguyên và Môi trường, Tổng Công ty Điện lực thành phố Hà Nội - Thành viên;
5. Đại diện Lãnh đạo, cán bộ các phòng nghiệp vụ thuộc Công an Thành phố - Thành viên;
6. Đại diện lãnh đạo UBND cấp huyện nơi có cơ sở được lựa chọn kiểm tra - Thành viên;
7. Công an Thành phố cử 01 đồng chí làm Thư ký đoàn kiểm tra;
8. Mời cơ quan báo, đài Thành phố phối hợp tham gia đưa tin, bài trên các phương tiện thông tin truyền thông: Đài Truyền hình Hà Nội, Báo Hà Nội mới, Báo Kinh tế đô thị, Báo An ninh thủ đô...
(Trong trường hợp đồng chí Trưởng đoàn bận công tác, giao đồng chí Phó Trưởng đoàn Thường trực chịu trách nhiệm duy trì việc kiểm tra của Đoàn)
V. PHƯƠNG PHÁP KIỂM TRA
1. Đối với UBND các cấp
- Kiểm tra việc quán triệt, lãnh đạo, chỉ đạo tổ chức triển khai thực hiện các văn bản của Thành ủy, HĐND Thành phố, UBND Thành phố.
- Kết quả thực hiện theo chức năng, nhiệm vụ được phân công trong công tác QLNN về các lĩnh vực đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện, an toàn về PCCC và CNCH.
- Kiểm tra đối chiếu với báo cáo, hồ sơ, tài liệu của các đơn vị, từ đó tổng hợp, đánh giá kết quả việc triển khai thực hiện theo chức năng nhiệm vụ được phân công, đồng thời hướng dẫn giải pháp khắc phục các tồn tại, vướng mắc.
2. Đối với Công an các cấp
- Kiểm tra công tác tham mưu cấp ủy chính quyền địa phương; việc quán triệt, chỉ đạo triển khai, thực hiện công tác QLNN về PCCC và CNCH theo phân công, phân cấp.
- Kiểm tra đối chiếu với báo cáo, hồ sơ, tài liệu của các đơn vị, từ đó tổng hợp, đánh giá kết quả việc triển khai thực hiện theo chức năng nhiệm vụ được phân công, đồng thời hướng dẫn giải pháp khắc phục các tồn tại, vướng mắc.
3. Đối với Công ty điện lực thành viên cấp huyện, Hợp tác xã kinh doanh điện
- Kiểm tra việc thực hiện chỉ đạo của Thành phố, Sở Công Thương, Tổng Công ty điện lực thành phố Hà Nội trong lĩnh vực điện, việc kiểm tra an toàn sử dụng điện sau công tơ, xử lý các vi phạm trong sử dụng điện đối với các hộ gia đình, cơ sở trên địa bàn thuộc phạm vi quản lý.
- Kiểm tra đối chiếu với báo cáo, hồ sơ, tài liệu của các đơn vị, từ đó tổng hợp, đánh giá kết quả việc triển khai thực hiện theo chức năng nhiệm vụ được phân, đồng thời hướng dẫn giải pháp khắc phục các tồn tại, vướng mắc.
4. Đối với cơ sở: Kiểm tra trực tiếp tại cơ sở việc chấp hành các quy định của pháp luật trong lĩnh vực đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện, an toàn về PCCC và CNCH của cơ sở; các điều kiện an toàn thực tế liên quan đến lĩnh vực điện, PCCC và CNCH
VI. PHÂN CÔNG NHIỆM VỤ
1. Công an Thành phố
- Chủ trì, tham mưu Chủ tịch UBND Thành phố thành lập Đoàn kiểm tra liên ngành cấp Thành phố.
- Chủ trì, phối hợp với các Sở, ngành: Công thương, Xây dựng, Quy hoạch - Kiến trúc, Tài nguyên và Môi trường, Tổng Công ty Điện lực thành phố Hà Nội xây dựng đề cương chi tiết phục vụ kiểm tra. Đề xuất đồng chí Trưởng đoàn phân công nội dung, nhiệm vụ cụ thể cho các đơn vị, thành viên Đoàn kiểm tra.
- Nghiên cứu, đề xuất đơn vị, cơ sở được kiểm tra, thời gian kiểm tra; chuẩn bị các điều kiện phục vụ công tác kiểm tra; thông báo lịch kiểm tra tới các thành viên Đoàn Kiểm tra.
- Thực hiện kiểm tra các nội dung liên quan đến công tác QLNN về PCCC và CNCH; việc thực hiện các quy định của pháp luật, các điều kiện an toàn PCCC và CNCH thực tế tại cơ sở...
- Chủ trì việc triển khai thực hiện Kế hoạch kiểm tra; tổng hợp, xây dựng Báo cáo về kết quả kiểm tra; tham mưu UBND Thành phố kịp thời chỉ đạo, giải quyết những tồn tại, hạn chế, khó khăn, vướng mắc, bất cập khi kiểm tra.
2. Văn phòng UBND Thành phố
- Phối hợp với Công an Thành phố tham mưu UBND Thành phố thành lập Đoàn kiểm tra liên ngành cấp Thành phố; nghiên cứu, đề xuất đồng chí Trưởng đoàn kiểm tra về đối tượng kiểm tra, thời gian kiểm tra, phân công nhiệm vụ cụ thể cho các đơn vị, thành viên Đoàn kiểm tra; chuẩn bị các điều kiện phục vụ công tác kiểm tra; đôn đốc, hướng dẫn các đơn vị triển khai thực hiện Kế hoạch kiểm tra...
- Phối hợp với Công an Thành phố thông báo lịch kiểm tra tới các thành viên Đoàn Kiểm tra.
3. Các Sở, ngành: Công Thương, Xây dựng, Quy hoạch - Kiến trúc, Tài nguyên và Môi trường, Kế hoạch và đầu tư, Tổng Công ty Điện lực thành phố Hà Nội
- Căn cứ chức năng, nhiệm vụ, lĩnh vực được phân công quản lý, phụ trách, xây dựng đề cương kiểm tra chi tiết thuộc các lĩnh vực đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện, gửi về CATP (qua Phòng Cảnh sát PCCC và CNCH, số 2 Dương Đình Nghệ, Cầu Giấy, Hà Nội) trước ngày 27/10/2023 để tổng hợp xây dựng đề cương chung.
- Tổ chức kiểm tra theo chức năng, nhiệm vụ được phân công việc thực hiện các quy định của pháp luật trong lĩnh vực đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện đối với các đơn vị, cơ sở được kiểm tra.
4. UBND các quận, huyện, thị xã và các cơ sở được kiểm tra
- Phân công các đơn vị, bộ phận chức năng có liên quan tham gia và chuẩn bị các điều kiện thực tế phục vụ Đoàn kiểm tra; xây dựng báo cáo, cung cấp thông tin, tài liệu thực hiện chức năng quản lý nhà nước, hồ sơ tài liệu thể hiện việc chấp hành các quy định của pháp luật trong các lĩnh vực đất đai, quy hoạch, đầu tư, xây dựng, an toàn điện, an toàn về PCCC và CNCH theo yêu cầu của Đoàn Kiểm tra.
- Tổ chức thực hiện các chỉ đạo, kiến nghị của Đoàn Kiểm tra, báo cáo kết quả thực hiện về UBND Thành phố theo quy định.
VII. TỔ CHỨC THỰC HIỆN
1. Căn cứ chức năng, nhiệm vụ được phân công, các đơn vị tổ chức triển khai thực hiện nghiêm túc nội dung của Kế hoạch.
2. Giao các Sở, ngành: Công an Thành phố, Công Thương, Xây dựng, Quy hoạch - Kiến trúc, Tài nguyên và Môi trường, Kế hoạch và Đầu tư, Tổng Công ty Điện lực thành phố Hà Nội:
(1) Phân công lãnh đạo, cán bộ tham gia Đoàn kiểm tra theo đúng thành phần tại Kế hoạch; gửi danh sách lãnh đạo, cán bộ tham gia Đoàn kiểm tra về UBND Thành phố (qua Công an Thành phố - Phòng Cảnh sát PCCC và CNCH) theo biểu mẫu gửi kèm Kế hoạch trước ngày 25/10/2023 để tập hợp.
(2) Chuẩn bị các tài liệu có liên quan phục vụ công tác kiểm tra theo quy định. Trong quá trình kiểm tra phải đánh giá sâu, cụ thể các ưu điểm, tồn tại, hạn chế của đơn vị, cơ sở; từ đó có đánh giá trách nhiệm cụ thể của các tập thể, cá nhân có liên quan trong công tác chỉ huy, chỉ đạo điều hành và tổ chức triển khai thực hiện; kiến nghị, đề xuất các giải pháp, biện pháp khắc phục.
3. Giao Công an Thành phố chủ trì, phối hợp các Sở, ngành: Công Thương, Xây dựng, Quy hoạch - Kiến trúc, Tài nguyên và Môi trường, Kế hoạch và Đầu tư, Tổng Công ty Điện lực thành phố Hà Nội tổ chức kiểm tra theo chức năng, nhiệm vụ được phân công và xây dựng báo cáo, báo cáo UBND Thành phố kết quả kiểm tra theo quy định./.
Nơi nhận: - Bộ Công an (V01, C07); - Thường trực Thành ủy; - Thường trực HĐND Thành phố; - Chủ tịch UBND Thành phố; - PCT TTUBND Thành phố; - Ủy ban MTTQVN Thành phố; - Các Sở, ban, ngành Thành phố; - UBND các quận, huyện, thị xã; - VPUB: CVP, PCVP C.N.Trang, NC, KGVX, KT, ĐT, TH; - Lưu: VT.
TM. ỦY BAN NHÂN DÂN KT. CHỦ TỊCH PHÓ CHỦ TỊCH Lê Hồng Sơn
........... ...................
CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc lập - Tự do - Hạnh phúc ---------------
Hà Nội, ngày tháng năm 2023
BIỂU MẪU DANH SÁCH
Cử thành viên tham gia Đoàn kiểm tra liên ngành kiểm tra việc thực hiện công tác phòng cháy, chữa cháy và cứu nạn, cứu hộ trên địa bàn Thành phố Hà Nội
TT
Họ và tên
Chức vụ, Đơn vị
SĐT liên hệ
Địa chỉ Email
Ghi chú
1
...
lồng nhau (bên trong) hay không
const memberID = 0;
const vbID = '8b9e40f0ab1530bac79aef492d9d4e2d';
// 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, '');
// 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 fixed position
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);
});
// Check: có CTTD pointer đang mở không?
const $visiblePointers = $('.pointer:visible');
const hadCTTDOpen = $visiblePointers.length > 0;
if (hadCTTDOpen) {
// CÓ CTTD đang mở → giữ rightdocinfo ẩn
console.log('ℹ️ CTTD pointer is visible, keeping rightdocinfo hidden');
} else {
// KHÔNG có CTTD → SHOW lại rightdocinfo
const $rightdocinfo = $('#rightdocinfo');
if ($rightdocinfo.length > 0) {
$rightdocinfo.show();
console.log('✅ Showing rightdocinfo back (no CTTD pointer)');
}
}
// 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');
}
// Panel đã song song với rightdocinfo → không cần MutationObserver nữa
console.log('✅ Panel running in standalone mode (parallel to rightdocinfo)');
// Resize event để update panel dimensions khi browser resize
let resizeTimer;
$(window).on('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
if (isPanelOpen && $('#phanTichPanel').length > 0) {
updatePanelDimensions();
console.log('✅ Panel dimensions updated on window resize');
}
}, 250); // Debounce 250ms
});
// Function để detect và áp dụng dimensions từ rightdocinfo
function updatePanelDimensions() {
const $panel = $('#phanTichPanel');
const $rightdocinfo = $('#rightdocinfo');
const $docRightCol = $('#doc-right-col');
if ($panel.length === 0) return;
// Ưu tiên: doc-right-col > rightdocinfo
let $reference = $docRightCol.length > 0 ? $docRightCol : $rightdocinfo;
// Nếu reference bị ẩn (display:none), tạm show để get dimensions
let wasHidden = false;
if ($reference.length > 0 && !$reference.is(':visible')) {
wasHidden = true;
$reference.css('visibility', 'hidden').show();
}
if ($reference.length > 0) {
const refWidth = $reference.outerWidth();
const refOffset = $reference.offset();
if (refWidth && refOffset) {
// Tính vị trí right từ edge màn hình
const windowWidth = $(window).width();
const rightPosition = windowWidth - (refOffset.left + refWidth);
$panel.css({
'width': refWidth + 'px',
'right': rightPosition + 'px'
});
console.log('✅ Panel dimensions updated:', {
width: refWidth + 'px',
right: rightPosition + 'px',
reference: $reference.attr('id')
});
} else {
console.warn('⚠️ Could not get dimensions from reference element');
}
// Restore trạng thái hidden nếu cần
if (wasHidden) {
$reference.hide().css('visibility', '');
}
} else {
console.warn('⚠️ No reference element found for panel dimensions');
}
}
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;
}
// Panel sẽ fixed position append vào body
const $rightdocinfo = $('#rightdocinfo');
// KHÔNG ẨN CTTD pointer - cho phép CTTD và panel cùng tồn tại
console.log('Panel opening, CTTD pointer can stay visible');
// ẨN rightdocinfo để tiết kiệm không gian
if ($rightdocinfo.length > 0) {
$rightdocinfo.hide();
console.log('Hidden rightdocinfo to save space');
}
// 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ó - fixed position append vào body
if ($('#phanTichPanel').length === 0) {
const panelHTML = `
Đang phân tích...
Đang phân tích...
`;
// Append vào body (fixed position không cần container cụ thể)
$('body').append(panelHTML);
// Detect width từ rightdocinfo và áp dụng cho panel
updatePanelDimensions();
// Trigger show và set flag
setTimeout(() => {
$('#phanTichPanel').addClass('show');
isPanelOpen = true;
console.log('✅ Panel opened (fixed position), isPanelOpen = true');
}, 10);
} else {
$('#phanTichPanelBody').html(`
Đang phân tích...
Đang phân tích...
`);
// Update dimensions khi re-open
updatePanelDimensions();
$('#phanTichPanel').addClass('show');
isPanelOpen = true;
console.log('✅ Panel re-opened (fixed position), 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();
});
// Bind nút refresh - phân tích lại
$(document).off('click.refreshPhanTich').on('click.refreshPhanTich', '.btn-refresh-phan-tich', function(e) {
e.preventDefault();
e.stopPropagation();
const $btn = $(this);
const $icon = $btn.find('i');
// Disable button và thêm animation
$btn.prop('disabled', true);
$icon.addClass('fa-spin');
console.log('🔄 Refresh: Phân tích lại address:', address);
// Show loading trong panel
$('#phanTichPanelBody').html(`
Đang phân tích lại...
Đang xóa cache và phân tích lại...
`);
// Gọi API xóa cache trước
deletePhanTichCache(address, vbID, function(deleteSuccess) {
if (deleteSuccess) {
console.log('✅ Cache deleted, now re-analyzing...');
// Sau khi xóa cache, gọi lại API phân tích
callPhanTichAPI(address, vbID, function() {
// Enable lại button
$btn.prop('disabled', false);
$icon.removeClass('fa-spin');
});
} else {
console.error('❌ Failed to delete cache');
$('#phanTichPanelBody').html(`
Lỗi! Không thể xóa cache. Vui lòng thử lại.
`);
$btn.prop('disabled', false);
$icon.removeClass('fa-spin');
}
});
});
// Gọi API phân tích (dùng function helper)
callPhanTichAPI(address, vbID);
}
// Helper: Gọi API phân tích (tách riêng để dùng lại)
function callPhanTichAPI(address, vbID, callback) {
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) + ' ';
if (response.from_cache) {
html += ' Cache ';
}
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(`
Lỗi! ${escapeHtml(response.error || 'Không thể phân tích điều luật.')}
Vui lòng thử lại sau.
`);
}
if (callback) callback();
},
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(`
Lỗi! Không thể kết nối đến server phân tích.
Chi tiết: ${escapeHtml(errorMsg)}
`);
if (callback) callback();
}
});
}
// Helper: Xóa cache phân tích
function deletePhanTichCache(address, vbID, callback) {
const randomServer = Math.floor(Math.random() * 10) + 1;
$.ajax({
url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/delete.phan.tich.cache.php',
type: 'POST',
contentType: 'application/json',
timeout: 10000,
data: JSON.stringify({
address: address,
vb_id: vbID
}),
success: function(response) {
console.log('Delete cache response:', response);
if (callback) callback(response.ok || false);
},
error: function(xhr, status, error) {
console.error('Delete cache error:', error);
if (callback) callback(false);
}
});
}
// 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;
// Parse address: vd "dieu_3_khoan_29" -> "Khoản 29 Điều 3"
// Address format: lớn đến nhỏ (phan > chuong > muc > dieu > khoan > diem)
const parts = address.split('_');
const displayParts = [];
for (let i = 0; i < parts.length; i += 2) {
if (i + 1 < parts.length) {
const type = getParentTypeName(parts[i]);
const num = parts[i + 1];
displayParts.push(type + ' ' + num);
}
}
// Reverse để hiển thị từ nhỏ đến lớn: "Khoản 29 Điều 3" (thay vì "Điều 3 Khoản 29")
return displayParts.reverse().join(' ');
}
function openPhanTichModal(address, vbID) {
// Tạo modal nếu chưa có
if ($('#modalPhanTich').length === 0) {
const modalHTML = `
Đang phân tích...
Đang phân tích...
`;
$('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(`
Lỗi! ${escapeHtml(response.error || 'Không thể phân tích điều luật.')}
Vui lòng thử lại sau.
`);
}
},
error: function(xhr, status, error) {
let errorMsg = error;
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMsg = xhr.responseJSON.error;
}
$('#modalPhanTichBody').html(`
Lỗi! Không thể kết nối đến server phân tích.
Chi tiết: ${escapeHtml(errorMsg)}
`);
}
});
}
// 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');
}
// Biến lưu element đang hover
let currentHoveredElement = null;
let hoverDebounceTimer = null;
// Dùng mousemove để track chính xác element nào đang được hover
$(document).on('mousemove', '#tab_noi_dung_vb', function(e) {
// Tìm element gần nhất (phan, chuong, muc, dieu, khoan, diem) tại vị trí chuột
const $target = $(e.target).closest('phan, chuong, muc, tieumuc, dieu, khoan, diem');
if ($target.length === 0) {
// Không hover vào element nào
return;
}
const address = $target.attr('address');
// Nếu đang hover vào cùng element → skip
if (currentHoveredElement && currentHoveredElement[0] === $target[0]) {
return;
}
// Clear debounce timer cũ
if (hoverDebounceTimer) {
clearTimeout(hoverDebounceTimer);
}
// Debounce để tránh trigger quá nhiều
hoverDebounceTimer = setTimeout(function() {
// Element thay đổi
console.log('Hover changed to:', address);
// Set flag hovering cho element mới
$target.data('hovering', true);
// Cancel timeout nếu có
const timeoutId = $target.data('hideTimeout');
if (timeoutId) {
clearTimeout(timeoutId);
}
// Ẩn badge của TẤT CẢ elements khác
$('#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($target)
.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ó
if (address && $target.find('.badge-phan-tich-container[data-for="' + address + '"]').length === 0) {
const parentType = getParentTypeName($target.prop('tagName').toLowerCase());
const $badge = $('Phân tích ');
console.log('Creating badge for address:', address, 'parentType:', parentType);
$target.append($badge);
$target.addClass('has-phan-tich-badge');
}
// Show badge cho element này
if ($target.find('.badge-phan-tich-container').length > 0) {
showPhanTichBadgeForParent($target);
}
// Update current hovered element
currentHoveredElement = $target;
}, 50); // Debounce 50ms
});
// Event delegation cho hover ra khỏi #tab_noi_dung_vb
$(document).on('mouseleave', '#tab_noi_dung_vb', function(e) {
// Clear current hovered element
currentHoveredElement = null;
// Ẩn tất cả badge không đang analyzing sau một khoảng thời gian
setTimeout(function() {
if (currentHoveredElement === null) {
// Chỉ ẩn nếu thực sự không hover vào element nào
$('#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')
.each(function() {
const $el = $(this);
const $badge = $el.find('.badge-phan-tich-container');
if ($badge.length && !$badge.data('analyzing')) {
$badge.css({display: 'none'});
}
});
console.log('Mouse left tab_noi_dung_vb, hiding all badges');
}
}, 300);
});
// Event delegation cho hover ra khỏi parent (giữ lại cho badge behavior)
$(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
$(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
$('.badge-phan-tich-container').each(function() {
const $badge = $(this);
if (!$badge.data('analyzing') && !$badge.hasClass('analyzing')) {
$badge.css({display: 'none'});
console.log('Hiding badge:', $badge.attr('data-for'));
}
});
});
// 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);
}
});
Tra cứu thuật ngữ với từ hoặc cụm từ đã chọn?
×
Kế hoạch 256/KH-UBND năm 2023 về kiểm tra việc thực hiện quy định của pháp luật trong các lĩnh vực có liên quan đến công tác phòng cháy chữa cháy và cứu nạn cứu hộ trên địa bàn Thành phố Hà Nội