Hệ thống pháp luật

UỶ BAN NHÂN DÂN
TỈNH SƠN LA
-------

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

Số: 2349/HD-UBND

Sơn La, ngày 26 tháng 6 năm 2023

 

HƯỚNG DẪN

CHỨC NĂNG, NHIỆM VỤ, QUYỀN HẠN VÀ CƠ CẤU TỔ CHỨC CỦA VĂN PHÒNG HỘI ĐỒNG NHÂN DÂN VÀ ỦY BAN NHÂN DÂN CÁC HUYỆN, THÀNH PHỐ

Căn cứ Nghị định số 37/2014/NĐ-CP ngày 05 tháng 5 năm 2014 của Chính phủ quy định tổ chức các cơ quan chuyên môn thuộc Ủy ban nhân dân huyện, quận, thị xã, thành phố thuộc tỉnh; Nghị định số 108/2020/NĐ-CP ngày 14 tháng 9 năm 2020 của Chính phủ sửa đổi, bổ sung một số điều của Nghị định số 37/2014/NĐ-CP ngày 05 tháng 5 năm 2014 của Chính phủ và các văn bản quy định, hướng dẫn của trung ươngI. VỊ TRÍ VÀ CHỨC NĂNG

1. Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện là cơ quan chuyên môn thuộc Uỷ ban nhân dân cấp huyện, là bộ máy tham mưu giúp việc của Ủy ban nhân dân, Chủ tịch Ủy ban nhân dân (bao gồm cả Phó Chủ tịch Ủy ban nhân dân cấp huyện) và Thường trực Hội đồng nhân dân cấp huyện.

2. Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện có chức năng:

a) Tham mưu tổng hợp cho Hội đồng nhân dân và Ủy ban nhân dân về: Hoạt động của Hội đồng nhân dân, Ủy ban nhân dân; tham mưu cho Chủ tịch Ủy ban nhân dân về chỉ đạo, điều hành của Chủ tịch Ủy ban nhân dân; kiểm soát thủ tục hành chính; cung cấp thông tin phục vụ quản lý và hoạt động của Hội đồng nhân dân, Ủy ban nhân dân và các cơ quan nhà nước ở địa phương; bảo đảm cơ sở vật chất, kỹ thuật cho hoạt động của Hội đồng nhân dân và Ủy ban nhân dân; tổ chức triển khai thực hiện cơ chế một cửa, một cửa liên thông trong giải quyết thủ tục hành chính thuộc phạm vi, chức năng quản lý của Ủy ban nhân dân cấp huyện; hướng dẫn, tiếp nhận hồ sơ của cá nhân, tổ chức trên tất cả các lĩnh vực thuộc thẩm quyền giải quyết của Ủy ban nhân dân cấp huyện, chuyển hồ sơ đến các cơ quan chuyên môn thuộc Ủy ban nhân dân cấp huyện giải quyết và nhận kết quả để trả cho cá nhân, tổ chức; quản lý hoạt động của Ban tiếp công dân theo đúng quy định của pháp luật.

b) Tham mưu, giúp Ủy ban nhân dân cấp huyện thực hiện quản lý nhà nước về y tế: Y tế dự phòng; khám bệnh, chữa bệnh, phục hồi chức năng; y dược cổ truyền; sức khỏe sinh sản; dân số; trang thiết bị y tế; dược; mỹ phẩm; an toàn thực phẩm; bảo hiểm y tế trên địa bàn.

c) Tham mưu, giúp Ủy ban nhân dân cấp huyện thực hiện chức năng quản lý nhà nước về công tác ngoại vụ, biên giới (đối với đơn vị hành chính cấp huyện có đường biên giới lãnh thổ quốc gia trên đất liền).

3. Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện có tư cách pháp nhân, có con dấu và tài khoản riêng; chịu sự chỉ đạo, quản lý về tổ chức, biên chế và công tác của Ủy ban nhân dân cấp huyện.

II. NHIỆM VỤ VÀ QUYỀN HẠN

Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện thực hiện các nhiệm vụ, quyền hạn quy định tại Nghị định số 37/2014/NĐ-CP; Nghị định số 108/2020/NĐ-CP và những nhiệm vụ, quyền hạn cụ thể sau:

1. Tham mưu tổng hợp, giúp HĐND và UBND cấp huyện

a) Xây dựng, quản lý chương trình công tác của HĐND, UBND cấp huyện theo quy định của pháp luật;

b) Theo dõi, đôn đốc các cơ quan chuyên môn thuộc UBND cấp huyện (sau đây viết tắt là cơ quan), UBND cấp xã, các cơ quan, tổ chức liên quan thực hiện chương trình công tác của HĐND, UBND cấp huyện và Quy chế làm việc của HĐND, UBND cấp huyện;

c) Phối hợp thường xuyên với các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan trong quá trình chuẩn bị và hoàn chỉnh các đề án, dự án, dự thảo văn bản quy phạm pháp luật, trình HĐND, UBND cấp huyện xem xét, quyết định theo quy định của pháp luật;

d) Thẩm tra về trình tự, thủ tục chuẩn bị và có ý kiến đánh giá độc lập đối với các đề án, dự án, dự thảo văn bản quy phạm pháp luật, các báo cáo quan trọng theo chương trình công tác của HĐND, UBND cấp huyện và các công việc khác do các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan trình HĐND, UBND cấp huyện;

đ) Xây dựng các đề án, dự án, dự thảo văn bản quy phạm pháp luật và các báo cáo theo sự phân công của HĐND, UBND cấp huyện;

e) Thực hiện công tác kiểm soát thủ tục hành chính và tổ chức thực hiện cơ chế một cửa, một cửa liên thông trong giải quyết thủ tục hành chính; Trực tiếp quản lý Bộ phận Tiếp nhận và Trả kết quả cấp huyện;

g) Tiếp nhận, xử lý phản ánh, kiến nghị của cá nhân, tổ chức về quy định hành chính thuộc phạm vi, thẩm quyền quản lý của UBND, Chủ tịch UBND cấp huyện theo quy định của pháp luật;

h) Chủ trì, phối hợp với các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan chuẩn bị nội dung, phục vụ phiên họp thường kỳ, chuyên đề, các cuộc họp và hội nghị chuyên đề khác của HĐND, UBND cấp huyện, các cuộc họp của Thường trực HĐND, Chủ tịch, các Phó Chủ tịch UBND cấp huyện;

i) Tham mưu, giúp UBND huyện tổ chức công tác tiếp công dân theo quy định của pháp luật hiện hành cho đến khi có các quy định mới của pháp luật về vấn đề này;

k) Tham mưu, giúp Uỷ ban nhân dân huyện về công tác ký kết và thực hiện thỏa thuận quốc tế của Uỷ ban nhân dân cấp xã ở khu vực biên giới (đối với đơn vị hành chính cấp huyện có đường biên giới lãnh thổ quốc gia trên đất liền).

2. Tham mưu, giúp UBND, Chủ tịch UBND cấp huyện thực hiện chức năng quản lý nhà nước về y tế theo nhiệm vụ và quyền hạn quy định tại Thông tư sô 37/2021/TT-BYT như sau:

a) Trình UBND cấp huyện dự thảo quyết định; quy hoạch, kế hoạch phát triển y tế trung hạn và hằng năm; chương trình, biện pháp tổ chức thực hiện các nhiệm vụ cải cách hành chính nhà nước thuộc lĩnh vực y tế trên địa bàn;

b) Trình Chủ tịch UBND cấp huyện dự thảo các văn bản thuộc thẩm quyền ban hành của Chủ tịch UBND cấp huyện theo phân công về y tế trên địa bàn;

c) Tổ chức thực hiện các văn bản pháp luật, quy hoạch, kế hoạch về y tế sau khi được cơ quan có thẩm quyền phê duyệt; thông tin, tuyên truyền, phổ biến, giáo dục pháp luật; theo dõi thi hành pháp luật thuộc lĩnh vực y tế;

d) Giúp UBND cấp huyện quản lý nhà nước đối với các doanh nghiệp, tổ chức kinh tế tập thể, kinh tế tư nhân; hướng dẫn và kiểm tra đối với các hội và tổ chức phi chính phủ tham gia hoạt động trong lĩnh vực y tế trên địa bàn huyện theo quy định của pháp luật;

đ) Hướng dẫn chuyên môn, nghiệp vụ về lĩnh vực y tế đối với cán bộ, công chức xã, phường, thị trấn;

e) Tổ chức nghiên cứu ứng dụng khoa học công nghệ và đổi mới sáng tạo; xây dựng hệ thống thông tin, lưu trữ phục vụ công tác quản lý nhà nước và chuyên môn nghiệp vụ thuộc lĩnh vực y tế;

g) Thực hiện công tác thông tin, báo cáo định kỳ và đột xuất về tình hình thực hiện nhiệm vụ được giao theo quy định của UBND cấp huyện và Sở Y tế;

h) Kiểm tra, tham gia thanh tra về lĩnh vực y tế đối với tổ chức, cá nhân trong việc thực hiện các quy định của pháp luật; giải quyết khiếu nại, tố cáo; phòng chống tham nhũng, thực hành tiết kiệm, chống lãng phí trong lĩnh vực y tế theo quy định của pháp luật và phân công của UBND cấp huyện. Thường trực Ban chỉ đạo phòng, chống dịch bệnh, Ban chỉ đạo liên ngành về an toàn thực phẩm cấp huyện.

3. Tham mưu tổng hợp, giúp Chủ tịch UBND cấp huyện:

a) Xây dựng, trình Chủ tịch UBND cấp huyện phê duyệt và đôn đốc thực hiện chương trình công tác năm, 6 tháng, quý, tháng, tuần của Chủ tịch UBND cấp huyện, kiến nghị với Chủ tịch UBND cấp huyện những nhiệm vụ trọng tâm, trọng điểm cần tập trung chỉ đạo, điều hành các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan trong từng thời gian nhất định;

b) Kiến nghị với Chủ tịch UBND cấp huyện giao các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan xây dựng các đề án, dự án, dự thảo văn bản pháp luật đề trình cấp có thẩm quyền quyết định;

c) Thẩm tra về trình tự, thủ tục chuẩn bị và có ý kiến đánh giá độc lập đối với các đề án, dự án, dự thảo văn bản, báo cáo theo chương trình công tác của Chủ tịch UBND cấp huyện và các công việc khác do các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan trình Chủ tịch UBND cấp huyện;

d) Chủ trì, phối hợp với các cơ quan, UBND cấp xã, các cơ quan tổ chức liên quan hoàn chỉnh nội dung, thủ tục, hồ sơ và dự thảo văn bản để trình Chủ tịch UBND cấp huyện xem xét, quyết định đối với những công việc thường xuyên khác;

đ) Chủ trì làm việc với lãnh đạo cơ quan, các tổ chức, cá nhân liên quan để giải quyết những vấn đề thuộc thẩm quyền của Chủ tịch UBND cấp huyện mà các cơ quan, UBND cấp xã còn có ý kiến khác nhau theo ủy quyền của Chủ tịch UBND cấp huyện;

e) Chủ trì soạn thảo, biên tập hoặc thẩm định, chỉnh sửa lần cuối các dự thảo báo cáo các bài phát biểu quan trọng của Chủ tịch UBND cấp huyện;

g) Chỉ đạo thực hiện các Quy chế phối hợp công tác giữa HĐND, UBND cấp huyện với các cơ quan của Đảng, Ủy ban Mặt trận Tổ quốc và các tổ chức chính trị xã hội, Tòa án nhân dân, Viện kiểm sát nhân dân cấp huyện;

h) Kiểm tra thực hiện những công việc thuộc thẩm quyền kiểm tra của Chủ tịch UBND cấp huyện đối với các cơ quan, UBND cấp xã, các cơ quan, tổ chức liên quan để báo cáo và kiến nghị với Chủ tịch UBND cấp huyện các biện pháp cần thiết nhằm đôn đốc thực hiện và bảo đảm chấp hành kỷ cương, kỷ luật hành chính;

i) Đề nghị các cơ quan, HĐND, UBND cấp xã, các cơ quan, tổ chức liên quan báo cáo tình hình, kết quả thực hiện các văn bản chỉ đạo, điều hành của HĐND, UBND và Chủ tịch UBND cấp huyện;

k) Được yêu cầu các cơ quan, HĐND, UBND cấp xã, các cơ quan, tổ chức liên quan cung cấp tài liệu, số liệu và văn bản liên quan hoặc tham dự các cuộc họp, làm việc để nắm tình hình, phục vụ công tác chỉ đạo, điều hành của HĐND, UBND và Chủ tịch UBND cấp huyện.

4. Bảo đảm thông tin phục vụ công tác lãnh đạo, chỉ đạo, điều hành của HĐND, UBND và Chủ tịch UBND cấp huyện:

a) Thực hiện chế độ báo cáo định kỳ và đột xuất với Chủ tịch UBND cấp huyện; thông tin để các thành viên UBND cấp huyện, Thủ trưởng cơ quan thuộc UBND cấp huyện, Chủ tịch HĐND, UBND cấp huyện, các cơ quan của Đảng, Nhà nước và các cơ quan, tổ chức liên quan về tình hình kinh tế - xã hội của địa phương, hoạt động của HĐND, UBND cấp huyện, công tác lãnh đạo, chỉ đạo, điều hành của Chủ tịch UBND cấp huyện;

b) Cung cấp thông tin cho công chúng và các hoạt động chủ yếu, những quyết định quan trọng của HĐND, UBND và Chủ tịch UBND cấp huyện, những sự kiện kinh tế, chính trị, xã hội nổi bật mà dư luận quan tâm theo quy định pháp luật và chỉ đạo của Chủ tịch UBND cấp huyện;

c) Quản lý và duy trì hoạt động mạng tin học của HĐND, UBND cấp huyện;

d) Quản lý và duy trì hệ thống quản lý văn bản điều hành, phòng họp không giấy tờ eCabinet;

đ) Quản lý, sử dụng con dấu, thiết bị lưu khóa bí mật của HĐND, UBND, Văn phòng HĐND và UBND cấp huyện theo quy định của pháp luật.

5. Bảo đảm các điều kiện vật chất, kỹ thuật cho hoạt động của HĐND, UBND cấp huyện, Chủ tịch UBND cấp huyện.

6. Xây dựng, ban hành các văn bản thuộc thẩm quyền của Văn phòng HĐND và UBND cấp huyện theo quy định của pháp luật.

7. Tổ chức việc phát hành, quản lý, lưu trữ các văn bản của HĐND, UBND và Chủ tịch UBND cấp huyện; thực hiện chế độ bảo vệ bí mật Nhà nước theo quy định.

8. Tổ chức nghiên cứu, thực hiện và ứng dụng các đề tài nghiên cứu khoa học.

9. Quản lý tổ chức bộ máy, biên chế; thực hiện chế độ tiền lương và các chế độ, chính sách đãi ngộ, khen thưởng, kỷ luật; đào tạo, bồi dưỡng về chuyên môn, nghiệp vụ đối với cán bộ, công chức thuộc Văn phòng HĐND và UBND cấp huyện theo quy định pháp luật và phân cấp.

10. Quản lý tài chính, tài sản được giao theo quy định của pháp luật và phân cấp của UBND cấp huyện.

11. Thực hiện các nhiệm vụ, quyền hạn khác do HĐND, UBND và Chủ tịch UBND cấp huyện giao hoặc theo quy định của pháp luật.

III. CƠ CẤU TỔ CHỨC

1. Lãnh đạo Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện:

a) Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện có Chánh Văn phòng, các Phó Chánh Văn phòng. Số lượng Phó Chánh Văn phòng do Ủy ban nhân dân huyện, thành phố quyết định theo biên chế được giao;

b) Chánh Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện là người đứng đầu Văn phòng HĐND và UBND cấp huyện, là Ủy viên UBND cấp huyện do HĐND cấp huyện bầu, do Chủ tịch UBND cấp huyện bổ nhiệm, chịu trách nhiệm trước HĐND, UBND và Chủ tịch UBND cấp huyện và trước pháp luật về toàn bộ hoạt động của Văn phòng; thực hiện nhiệm vụ, quyền hạn của Ủy viên UBND cấp huyện theo Quy chế làm việc và phân công của UBND cấp huyện; đồng thời là chủ tài khoản cơ quan Văn phòng HĐND và UBND cấp huyện;

c) Phó Chánh Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện là cấp phó của người đứng đầu Văn phòng HĐND và UBND cấp huyện thuộc UBND cấp huyện, giúp Chánh Văn phòng thực hiện, theo dõi một số mặt công tác và chịu trách nhiệm trước Chánh Văn phòng, trước pháp luật về nhiệm vụ được phân công. Khi Chánh Văn phòng vắng mặt, một Phó Chánh Văn phòng được Chánh Văn phòng ủy quyền điều hành các hoạt động của Văn phòng HĐND và UBND cấp huyện;

d) Việc bổ nhiệm, điều động, luân chuyển, khen thưởng, kỷ luật, miễn nhiệm, cho từ chức, thực hiện chế độ, chính sách đối với Chánh Văn phòng, Phó Chánh Văn phòng do Chủ tịch UBND cấp huyện quyết định theo quy định của pháp luật và theo phân cấp về công tác cán bộ.

2. Các bộ phận tham mưu, giúp việc: Căn cứ vào chức năng, nhiệm vụ và tình hình thực tế của địa phương, Văn phòng HĐND và UBND cấp huyện sắp xếp phù hợp các bộ phận tham mưu, giúp việc nhưng phải bảo đảm có các bộ phận: Tiếp nhận và trả kết quả; Tiếp công dân; Nghiên cứu, tổng hợp; Văn thư - Lưu trữ; Kế toán...

IV. BIÊN CHẾ

1. Biên chế công chức của Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện do cấp thẩm quyền quyết định trong tổng biên chế công chức của cơ quan có thẩm quyền giao hàng năm.

2. Việc bố trí công tác đối với công chức của Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện phải căn cứ vào vị trí việc làm, cơ cấu ngạch công chức được giao hằng năm và phẩm chất, trình độ, năng lực của từng công chức.

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

1. Chánh Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện có trách nhiệm trình Uỷ ban nhân dân cấp huyện ban hành quy định cụ thể chức năng, nhiệm vụ, quyền hạn và tổ chức của Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện trên cơ sở phù hợp với các quy định của pháp luật hiện hành có liên quan và hướng dẫn này.

2. Trong quá trình tổ chức thực hiện, nếu có vấn đề phát sinh hoặc khó khăn, vướng mắc, đề nghị phản ánh kịp thời về Ủy ban nhân dân tỉnh Sơn La (thông qua Văn phòng Ủy ban nhân dân tỉnh Sơn La) để được xem xét, giải quyết.

VI. TRÁCH NHIỆM THỰC HIỆN

Giao Ủy ban nhân dân cấp huyện:

1. Chỉ đạo Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện chủ trì, phối hợp với Phòng Nội vụ, Phòng Tư pháp và cơ quan có liên quan tham mưu Ủy ban nhân dân cấp huyện ban hành Quyết định quy định chức năng, nhiệm vụ, quyền hạn và tổ chức của Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện kịp thời, theo đúng trình tự, thủ tục quy định.

2. Báo cáo kết quả ban hành kèm Quyết định quy định chức năng, nhiệm vụ, quyền hạn và tổ chức của Văn phòng Hội đồng nhân dân và Ủy ban nhân dân cấp huyện về Sở Nội vụ để tổng hợp, báo cáo Ủy ban nhân dân tỉnh; gửi Văn phòng Đoàn đại biểu Quốc hội và HĐND tỉnh, Văn phòng UBND tỉnh và Sở Y tế để biết, chỉ đạo trong quá trình thực hiện nhiệm vụ./.

 


Nơi nhận:
- Thường trực HĐND tỉnh;
- Chủ tịch, các Phó Chủ tịch UBND tỉnh;
- VP Đoàn ĐBQH và HĐND tỉnh;
- Sở Nội vụ; Sở Y tế; Sở Tư pháp;
- TT. HĐND, UBND huyện, thành phố;
- VP. HĐND và UBND huyện, thành phố;
- LĐ VP UBND tỉnh;
- Các phòng thuộc VP UBND tỉnh;
- Trung tâm thông tin tỉnh;
- Lưu: VT, NC. Hiệp (10b)

TM. ỦY BAN NHÂN DÂN
CHỦ TỊCH




Hoàng Quốc Khánh

 



lồng nhau (bên trong) hay không const memberID = 0; const vbID = '5540e3f59628c20831d1b4ef2d095c4e'; // 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 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 = `
    Phân tích điều luật
    Đ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(` `); $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(` `); } 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(` `); 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 = ` `; $('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'); } // 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); } });