ỦY BAN NHÂN DÂN TỈNH TIỀN GIANG -------
CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc lập - Tự do - Hạnh phúc ---------------
Số: 75/KH-UBND
Tiền Giang, ngày 06 tháng 3 năm 2023
KẾ HOẠCH
THÔNG TIN, TUYÊN TRUYỀN VỀ CÔNG TÁC CẢI CÁCH HÀNH CHÍNH NĂM 2023 TRÊN ĐỊA BÀN TỈNH TIỀN GIANG
Căn cứ Quyết định số 82/QĐ-BNV ngày 15/02/2023 của Bộ trưởng Bộ Nội vụ về ban hành Kế hoạch thông tin, tuyên truyền cải cách hành chính năm 2023;
Căn cứ Quyết định số 2703/QĐ-UBND ngày 18/10/2021 của Ủy ban nhân dân tỉnh về ban hành Chương trình tổng thể cải cách hành chính (CCHC) nhà nước của tỉnh Tiền Giang, giai đoạn 2021 - 2030; Quyết định số 45/QĐ-UBND ngày 10/01/2023 của Ủy ban nhân dân tỉnh về ban hành Kế hoạch thực hiện nhiệm vụ CCHC năm 2023 trên địa bàn tỉnh Tiền Giang;
Ủy ban nhân dân (UBND) tỉnh ban hành Kế hoạch thông tin, tuyên truyền về công tác CCHC năm 2023 trên địa bàn tỉnh với các nội dung sau:
I. MỤC ĐÍCH, YÊU CẦU
1. Mục đích
a) Cung cấp thông tin, tuyên truyền, phổ biến đến các tổ chức trong hệ thống chính trị, các tầng lớp Nhân dân, đội ngũ cán bộ, công chức, viên chức và người lao động về công tác CCHC; trọng tâm là cải cách tổ chức bộ máy hành chính, cải cách chế độ công vụ, công chức; đẩy mạnh cải cách thủ tục hành chính (TTHC) và phát triển Chính quyền điện tử, Chính quyền số.
b) Nâng cao chất lượng, hiệu quả hoạt động của các cấp chính quyền, cơ quan nhà nước trên địa bàn tỉnh trong giải quyết công việc, giải quyết TTHC, cung cấp dịch vụ cho người dân, tổ chức, doanh nghiệp; xây dựng hình ảnh đội ngũ cán bộ, công chức, viên chức Việt Nam gương mẫu, tận tụy, chuẩn mực, chuyên nghiệp, trách nhiệm, kỷ cương, tận tình, thân thiệnc) Tạo cơ hội cho cá nhân, tổ chức và doanh nghiệp được tiếp cận đầy đủ, chính xác, minh bạch thông tin về công tác CCHC; tạo đồng thuận trong xã hội đối với công tác CCHC; nâng cao sự hài lòng của người dân đối với sự phục vụ của các cơ quan hành chính nhà nước; phát huy vai trò giám sát, phối hợp của các tổ chức đoàn thể; vận động các lực lượng quần chúng nhân dân đóng góp ý kiến, hợp tác, tuân thủ, cùng tham gia thực hiện các nhiệm vụ CCHC của tỉnh.
2. Yêu cầu
a) Kế hoạch được triển khai, tổ chức thực hiện tại 100% các sở, ban, ngành tỉnh, UBND các huyện, thành phố, thị xã; được cụ thể hóa tại kế hoạch tuyên truyền CCHC của cơ quan, đơn vị, địa phương.
b) Nội dung thông tin, tuyên truyền bám sát Chương trình tổng thể CCHC nhà nước giai đoạn 2021 - 2030 của Chính phủ, của tỉnh, Kế hoạch thực hiện nhiệm vụ CCHC năm 2023; lồng ghép với các nội dung tuyên truyền, phổ biến các chủ trương, chính sách của Đảng, pháp luật của Nhà nước về cải cách lập pháp, cải cách tư pháp, xây dựng Nhà nước pháp quyền xã hội chủ nghĩa của dân, do dân, vì dân.
c) Hoạt động thông tin, tuyên truyền CCHC được tổ chức hiệu quả, thiết thực, kịp thời, thường xuyên; hình thức thông tin, tuyên truyền đa dạng, phong phú, thân thiện, phù hợp với nội dung tuyên truyền, phù hợp với từng khu vực, địa bàn, các nhóm đối tượng, giúp người dân, doanh nghiệp tiếp cận nhanh, hiệu quả; nội dung thông tin đầy đủ, chính xác, đơn giản, dễ hiểu, có tính định hướng dư luận.
II. ĐỐI TƯỢNG, NỘI DUNG, HÌNH THỨC TUYÊN TRUYỀN
1. Đối tượng tuyên truyền
Đối tượng là cán bộ, công chức, viên chức làm việc trong hệ thống cơ quan hành chính nhà nước từ tỉnh đến cơ sở, các tổ chức chính trị - xã hội, các đơn vị sự nghiệp công lập và các tầng lớp Nhân dân.
2. Nội dung tuyên truyền
Công tác thông tin, tuyên truyền CCHC năm 2023 tập trung vào những nội dung trọng tâm sau:
a) Các quan điểm, chủ trương của Đảng, chính sách pháp luật của Nhà nước, của tỉnh về CCHC, nhất là các kết quả thực hiện các nhiệm vụ CCHC năm 2023 của tỉnh và các sở, ban, ngành tỉnh và địa phương.
b) Vai trò, trách nhiệm của các cấp ủy đảng, của người đứng đầu cơ quan hành chính các cấp, người đứng đầu các tổ chức chính trị - xã hội, các đơn vị sự nghiệp công lập đối với việc triển khai thực hiện nhiệm vụ CCHC.
c) Về triển khai thực hiện các nhiệm vụ, kế hoạch về công tác CCHC năm 2023d) Tình hình triển khai, những kết quả đạt được và những tồn tại, hạn chế, nguyên nhân trong tổ chức thực hiện nhiệm vụ CCHC của các sở, ban, ngành tỉnh và địa phương, nhất là Chỉ số hài lòng của người dân, tổ chức đối với sự phục vụ của cơ quan hành chính nhà nước năm 2022 và kết quả đánh giá Chỉ số CCHC năm 2022 của các sở, ban, ngành tỉnh và địa phương.
đ) Tuyên truyền, phổ biến sâu rộng về tầm quan trọng, ý nghĩa, mục tiêu và tác động của CCHC đến phát triển kinh tế - xã hội của tỉnh; tuyên truyền các nội dung theo Chương trình tổng thể CCHC nhà nước giai đoạn 2021 - 2030 của Chính phủ, của tỉnh- Phối hợp hoàn thiện thể chế, các quy định pháp luật có liên quan đến sở hữu, doanh nghiệp nhà nước; nâng cao chất lượng công tác xây dựng, ban hành, kiểm tra, rà soát, hệ thống hóa văn bản quy phạm pháp luật.
- Thực hiện nghiêm Luật Ban hành văn bản quy phạm pháp luật và các văn bản hướng dẫn thi hành; kiểm soát, công khai các TTHC theo quy định pháp luật.
- Tình hình, kết quả triển khai thực hiện đổi mới, sắp xếp tổ chức bộ máy của các cơ quan hành chính nhà nước tinh gọn, hoạt động hiệu lực, hiệu quả; đổi mới hệ thống tổ chức và quản lý, nâng cao chất lượng và hiệu quả hoạt động của các đơn vị sự nghiệp công lập trên địa bàn tỉnh.
- Việc rà soát, điều chỉnh chức năng, nhiệm vụ, quyền hạn và tổ chức, sắp xếp lại các cơ quan, tổ chức, đơn vị; phân loại các cơ quan hành chính làm cơ sở xác định tổ chức bộ máy phù hợp; triển khai diện rộng cơ chế tự chủ, tự chịu trách nhiệm các đơn vị sự nghiệp dịch vụ công; hoàn thiện quy hoạch mạng lưới các đơn vị sự nghiệp công lập theo ngành, lĩnh vực. Phân loại đơn vị sự nghiệp để thực hiện các hình thức chuyển đổi phù hợp. Đẩy mạnh xã hội hóa các đơn vị sự nghiệp công lập gắn với tinh giản biên chế- Việc rà soát, hoàn thiện chức năng, nhiệm vụ, quyền hạn và cơ cấu tổ chức; việc sắp xếp kiện toàn tổ chức bộ máy các cấp; xây dựng, thực hiện đề án vị trí việc làm và cơ cấu công chức, viên chức; thực hiện phân công, phân cấp quản lý.
- Tình hình triển khai, kết quả, hiệu quả trong thực hiện các nội dung: cơ chế một cửa, một cửa liên thông trong giải quyết TTHC- Các quy định về quyền, nghĩa vụ, trách nhiệm, đạo đức của cán bộ, công chức, viên chức trong thực thi công vụ, nhiệm vụ; thực hiện quy tắc ứng xử, văn hóa giao tiếp, tác phong, thái độ phục vụ Nhân dân của cán bộ, công chức, viên chức; về tăng cường kỷ luật, kỷ cương hành chính trong các cơ quan, đơn vị.
- Tuyên truyền về xây dựng và phát triển Chính quyền điện tử, Chính quyền số, công tác chuyển đổi số trong các cơ quan, đơn vị, doanh nghiệp, việc ứng dụng công nghệ thông tin, cung cấp dịch vụ công trực tuyến, giá trị của giấy tờ điện tử nhất là chứng thực điện tử; việc triển khai Đề án phát triển ứng dụng dữ liệu về dân cư, định danh và xác thực điện tử phục vụ chuyển đổi số quốc gia giai đoạn 2022 - 2025, tầm nhìn đến năm 2030 trên địa bàn tỉnh; việc đẩy mạnh thương mại điện tử, thanh toán không dùng tiền mặt đối với chi trả trợ cấp xã hội, hỗ trợ an sinh xã hội và nhất là thu phí, lệ phí cho người dân, doanh nghiệp trong giải quyết TTHC...
- Tuyên truyền, phổ biến trong cộng đồng dân cư về các cách thức thực hiện TTHC qua dịch vụ công trực tuyến đối với các thủ tục đã được công bố tiếp nhận hồ sơ trực tuyến trên Cổng Dịch vụ công Quốc gia tại địa chỉ https://dichvucong.gov.vn và Cổng Dịch vụ công của tỉnh tại địa chỉ https://dichvucong.tiengiang.gov.vn; lợi ích của việc tạo tài khoản và sử dụng tài khoản trên Cổng Dịch vụ công Quốc gia.
- Tình hình triển khai Hệ thống cơ sở dữ liệu quốc gia về cán bộ, công chức, viên chức trong cơ quan nhà nước tại các sở, ban, ngành và địa phương.
- Kết quả công tác quản lý biên chế và tinh giản biên chế theo yêu cầu của các cơ quan Trung ươnge) Các mô hình, cơ chế đang được triển khai thí điểm, các điển hình tốt trong CCHC ở Trung ương và địa phương.
g) Quy định của pháp luật về mối quan hệ giữa Nhà nước và Nhân dân; quyền, nghĩa vụ và trách nhiệm của cá nhân, tổ chức trong việc tham gia và giám sát tiến trình CCHC. Nâng cao nhận thức, đổi mới tư duy và hành động sáng tạo; đổi mới lề lối làm việc, phương thức quản trị hiện đại, trên cơ sở đẩy mạnh ứng dụng công nghệ thông tin, thực hiện chuyển đổi số trong hoạt động của các cơ quan hành chính nhà nước. Tăng cường chỉ đạo, điều hành, xử lý công việc trên môi trường số; tổ chức họp, hội nghị bằng hình thức trực tuyến, hạn chế giấy tờ.
h) Tuyên truyền, giới thiệu công khai các địa chỉ, điện thoại đường dây nóng tiếp nhận phản ánh, kiến nghị về TTHC, quy định hành chính, tinh thần trách nhiệm, thái độ giao tiếp, ứng xử của cán bộ, công chức, viên chức với người dân.
k) Các nội dung khác phù hợp với nhiệm vụ trọng tâm hàng năm của CCHC, khi có văn bản mới của Trung ương, của tỉnh cần được phổ biến, thông tin, tuyên truyền sâu rộng đến mọi đối tượng tầng lớp Nhân dân.
3. Hình thức tuyên truyền
Trên cơ sở các văn bản chỉ đạo, hướng dẫn về công tác CCHC của Trung ương và nhất là của tỉnh, các cơ quan, đơn vị, địa phương tập hợp các nội dung chủ yếu, trọng tâm để thông tin, tuyên truyền thông qua các hình thức chủ yếu sau:
a) Tuyên truyền trực quan thông qua việc phát hành tờ gấp, pa nô, áp phích ... liên quan đến CCHC, phù hợp với từng mục tiêu, yêu cầu, nội dung tuyên truyền, phổ biến đến từng nhóm đối tượng.
b) Xây dựng kênh thông tin tuyên truyền về CCHC của tỉnh Tiền Giang trên nền tảng mạng xã hội (đã được các cơ quan có thẩm quyền kiểm duyệt, công nhận).
c) Tuyên truyền qua Tổng đài 1022 của tỉnh, app TiengiangS, tuyên truyền trực tiếp thông qua các hội nghị, cuộc họp, giao ban, tờ rơi... đến đội ngũ cán bộ, công chức, viên chức và người lao động trong cơ quan, đơn vị; thông qua sinh hoạt các tổ chức đảng, đoàn thể, tổ chức chính trị - xã hội, xã hội tự nguyện tới hội viên và quần chúng nhân dân; thông qua Tổ công nghệ số cộng đồng, đội ngũ cộng tác viên và người thân trong gia đình.
d) Thông tin, tuyên truyền thông qua các loại hình báo chí và huy động, sử dụng nhiều phương tiện thông tin, như: Đài Phát thanh và Truyền hình Tiền Giang, Báo Ấp Bắc, Trung tâm Văn hóa, Thông tin - Thể thao các huyện, thị xã, Đài Truyền thanh - Truyền hình thành phố Mỹ Tho, hệ thống Đài Truyền thanh các xã, phường, thị trấn, Cổng Thông tin điện tử của tỉnh, Bản tin CCHC tỉnh Tiền Giang (trên Trang thông tin điện tử của Sở Nội vụ) , Trang thông tin điện tử của các cơ quan, đơn vị.
đ) Tuyên truyền thông qua các cuộc thi tìm hiểu, các phong trào của đoàn viên, thanh niên, công chức, các lớp tập huấn, bồi dưỡng về CCHC cho đội ngũ cán bộ, công chức, viên chức. Lồng ghép nội dung CCHC trong các hội nghị tuyên truyền, phổ biến giáo dục pháp luật, trao đổi, tọa đàm, diễn đàn, đối thoại, tiếp xúc cử tri,... phù hợp với từng nhóm đối tượng. Tổ chức các cuộc thi viết trên báo chí, các hội thi, hội diễn cho tuyên truyền viên, báo cáo viên cấp cơ sở về CCHC.
e) Niêm yết công khai, minh bạch các TTHC đầy đủ, rõ ràng theo đúng quy định tại Bộ phận Tiếp nhận và Trả kết quả, tại nơi giải quyết TTHC bằng nhiều hình thức khác nhau như: niêm yết bằng văn bản giấy, trên Trang thông tin điện tử... Tổ chức hội nghị đối thoại với cá nhân, tổ chức về TTHC, giải quyết TTHC thuộc thẩm quyền của các cơ quan, đơn vị, địa phương.
g) Huy động cán bộ, công chức, viên chức, người lao động tích cực tham gia viết bài về CCHC.
h) Các hình thức thông tin, tuyên truyền khác phù hợp với đặc điểm, tình hình của cơ quan, đơn vị, địa phương.
III. KINH PHÍ THỰC HIỆN
Kinh phí phục vụ cho công tác tuyên truyền CCHC được cân đối từ nguồn kinh phí CCHC đã được bố trí trong dự toán ngân sách hàng năm theo phân cấp hiện hành và các nguồn kinh phí hợp pháp khác theo quy định.
IV. TỔ CHỨC THỰC HIỆN
1. Các sở, ban, ngành tỉnh; UBND các huyện, thành phố, thị xã
a) Căn cứ Kế hoạch này, xây dựng và tổ chức thực hiện có hiệu quả kế hoạch thông tin, tuyên truyền CCHC năm 2023 của cơ quan, đơn vị, địa phương, đảm bảo đầy đủ các nội dung và hình thức tuyên truyền phù hợp với tình hình, điều kiện của cơ quan, đơn vị, địa phương trong đó cần có đổi mới để đem lại hiệu quả thiết thực.
b) UBND các huyện, thành phố, thị xã chỉ đạo UBND các xã, phường, thị trấn thực hiện có hiệu quả việc thông tin, tuyên truyền về công tác CCHC ở xã, phường, thị trấn.
c) Báo cáo cụ thể tình hình, kết quả thực hiện nội dung thông tin, tuyên truyền về công tác CCHC của cơ quan, đơn vị, địa phương trong báo cáo CCHC định kỳ theo quy định.
2. Sở Nội vụ
a) Theo dõi, đôn đốc, kiểm tra các sở, ban, ngành tỉnh, UBND các huyện, thành phố, thị xã triển khai thực hiện Kế hoạch này. Chủ động xây dựng nội dung trọng tâm của CCHC cần tập trung tuyên truyền trong năm 2023.
b) Phối hợp với các cơ quan, đơn vị liên quan tổ chức cuộc thi tìm hiểu về chuyển đổi số, chính quyền số...
c) Tổng hợp, báo cáo các nội dung về thông tin, tuyên truyền trong công tác CCHC của tỉnh vào các báo cáo CCHC định kỳ.
3. Sở Thông tin và Truyền thông
a) Chủ trì hoặc phối hợp với các cơ quan, đơn vị liên quan tổ chức cuộc thi tìm hiểu về các chủ đề chuyển đổi số, xây dựng chính quyền điện tử ...
b) Xây dựng kênh thông tin truyền thông CCHC trên nền tảng mạng xã hội để tương tác với tổ chức, công dân.
c) Chủ trì tham mưu các nội dung tuyên truyền về Chính quyền điện tử, Chính quyền số về ứng dụng công nghệ thông tin trong các cơ quan nhà nước.
4. Văn phòng Ủy ban nhân dân tỉnh
a) Chủ trì, phối hợp với Sở Thông tin và Truyền thông hướng dẫn các cơ quan, đơn vị cập nhật, công khai đầy đủ, rõ ràng, đúng quy định các TTHC tại nơi giải quyết TTHC và trên Cổng thông tin điện tử tỉnh, Trang thông tin điện tử cơ quan, đơn vị.
b) Thực hiện tốt công tác thông tin, truyền thông về hoạt động kiểm soát TTHC và cơ chế một cửa, một cửa liên thông trên địa bàn tỉnh; về hoạt động của Trung tâm Phục vụ hành chính công và Kiểm soát TTHC, về tiếp nhận và trả kết quả giải quyết TTHC, công khai minh bạch TTHC trên Cổng thông tin điện tử của tỉnh.
5. Sở Tư pháp thực hiện lồng ghép tuyên truyền công tác CCHC với công tác tuyên truyền, phổ biến, giáo dục pháp luật trên địa bàn tỉnh.
6. Sở Tài chính chủ trì, phối hợp với các cơ quan, đơn vị có liên quan bố trí kinh phí thực hiện công tác thông tin, tuyên truyền theo phê duyệt của cấp có thẩm quyền.
7. Sở Kế hoạch và Đầu tư thực hiện tuyên truyền có hiệu quả các giải pháp cải thiện môi trường đầu tư, kinh doanh, nâng cao chỉ số năng lực cạnh tranh cấp tỉnh (PCI). Đẩy mạnh tuyên truyền thu hút đầu tư, hỗ trợ, khuyến khích thành lập mới doanh nghiệp và sử dụng có hiệu quả mọi nguồn lực để phục vụ cho đầu tư phát triển.
8. Sở Y tế chủ trì thực hiện tuyên truyền việc nâng cao chất lượng dịch vụ y tế công và triển khai thực hiện đo lường sự hài lòng của người dân đối với dịch vụ y tế công theo hướng dẫn của Bộ Y tế.
9. Sở Giáo dục và Đào tạo chủ trì thực hiện tuyên truyền việc nâng cao chất lượng dịch vụ giáo dục công và triển khai thực hiện đo lường sự hài lòng của người dân đối với dịch vụ giáo dục công theo hướng dẫn của Bộ Giáo dục và Đào tạo.
10. Sở Khoa học và Công nghệ chủ trì tuyên truyền việc xây dựng, áp dụng, duy trì và cải tiến hệ thống quản lý chất lượng theo Tiêu chuẩn quốc gia TCVN ISO 9001:2015 trong các cơ quan hành chính nhà nước.
11. Sở Văn hóa, Thể thao và Du lịch
a) Chủ trì tuyên truyền cơ chế, chính sách xã hội hóa trong các hoạt động văn hóa, thể thao và du lịch, nâng cao chất lượng dịch vụ văn hóa, thể thao và du lịch của tỉnh.
b) Chỉ đạo các đơn vị sự nghiệp văn hóa - nghệ thuật - thông tin xây dựng kịch bản, dàn dựng các tiết mục, chương trình thông tin lưu động, sân khấu hóa thông tin, tuyên truyền về công tác CCHC của tỉnh, biểu diễn phục vụ rộng rãi Nhân dân trong tỉnh.
12. Đài Phát thanh và Truyền hình tỉnh, Báo Ấp Bắc
a) Tiếp tục duy trì, mở rộng chuyên mục, chuyên trang, nâng cao chất lượng các chương trình về CCHC; xây dựng kênh thông tin CCHC trên nền tảng mạng xã hội để thu hút nhiều đối tượng được tuyên truyền.
b) Tập trung tuyên truyền các mục tiêu, nhiệm vụ CCHC trong năm của tỉnh.
c) Chủ động cập nhật, phản ánh thông tin, kết quả CCHC của các cơ quan, đơn vị, địa phương, bố trí giờ và thời lượng phát sóng, diện tích đăng tải thích hợp.
d) Xây dựng chương trình theo hình thức mới nhằm đẩy mạnh tuyên truyền, nâng cao nhận thức về CCHC cho các tầng lớp Nhân dân.
13. Đề nghị Ủy ban Mặt trận Tổ quốc Việt Nam tỉnh Tiền Giang và các tổ chức chính trị - xã hội tỉnh
Tăng cường thông tin, tuyên truyền CCHC trong lực lượng đoàn viên, hội viên từ tỉnh đến cơ sở và phối hợp với các cơ quan hành chính nhà nước triển khai các nội dung tuyên truyền chuyên đề, cụ thể (khi có yêu cầu).
Trên đây là Kế hoạch thông tin, tuyên truyền về công tác cải cách hành chính năm 2023 trên địa bàn tỉnh. Quá trình thực hiện Kế hoạch, nếu phát sinh vấn đề khó khăn, vướng mắc, các cơ quan, đơn vị báo cáo Ủy ban nhân dân tỉnh (qua Sở Nội vụ tổng hợp) xem xét, giải quyết./.
Nơi nhận: - Vụ CCHC - Bộ Nội vụ; - TTTU, TT HĐND tỉnh; - CT, các PCT UBND tỉnh; - UBMTTQ tỉnh; - Các sở, ban, ngành tỉnh; - UBND các huyện, thành, thị; - VPUB: CVP, các PCVP, P.NC, TTPVHCC&KSTT, TTTH-CB; - Đài PTTH tỉnh, Báo Ấp Bắc; - Cổng TTĐT tỉnh; - Lưu: VT, KSTT (Hiếu).
CHỦ TỊCH Nguyễn Văn Vĩnh
lồng nhau (bên trong) hay không
const memberID = 0;
const vbID = '20b9cee91893f554c5b8d9ff0049d0c4';
const unlockAllPhanTich = true;
// 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
// Typing effect state
let typingTimerId = null;
let typingCancelled = false;
// Thinking GIF state
let thinkingGifIntervalId = null;
let thinkingGifActive = false;
let thinkingGifCurrent = 0; // chỉ số GIF hiện tại 1..10
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, vb_ngaybanhanh: '2023-03-06 00:00:00 AM' };
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 (((unlockAllPhanTich) || memberID === 4 || memberID === 3 || memberID === 2) && 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 extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
const $badge = $('');
$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);
}, 3); // Đợi 300ms để CTTD render xong
}
},
complete: function() {
$element.removeClass('loading-content');
}
})
);
processQueue();
}
});
} catch(e) {
}
}
$(window).on('scroll resize', function () {
processVisibleParagraphs();
});
processVisibleParagraphs();
// Chức năng phân tích điều luật (mở theo lịch unlockAllPhanTich cho tất cả, nhưng khách click sẽ mở modal đăng nhập/mua gói)
if ((unlockAllPhanTich) || memberID === 4 || memberID === 3 || memberID === 2) {
// 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';
}
// Chuyển Telex -> Unicode cho giá trị (ví dụ: dd->đ, oo->ô, ow->ơ, aa->â, ee->ê, aw->ă, uw->ư)
function telexToUnicode(str) {
if (!str) return str;
// Giữ nguyên số
if (/^\d+$/.test(str)) return str;
let s = String(str);
// dd / ĐĐ
s = s.replace(/dd/g, 'đ');
s = s.replace(/DD/g, 'Đ');
// nguyên âm có mũ/dấu
s = s.replace(/aa/g, 'â').replace(/AA/g, 'Â');
s = s.replace(/ee/g, 'ê').replace(/EE/g, 'Ê');
s = s.replace(/oo/g, 'ô').replace(/OO/g, 'Ô');
s = s.replace(/ow/g, 'ơ').replace(/OW/g, 'Ơ');
s = s.replace(/uw/g, 'ư').replace(/UW/g, 'Ư');
s = s.replace(/aw/g, 'ă').replace(/AW/g, 'Ă');
return s;
}
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 extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
const $badge = $('');
$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);
}
// Stop typing animation nếu đang chạy
stopThinkingTyping();
// 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
} else {
// KHÔNG có CTTD → SHOW lại rightdocinfo
const $rightdocinfo = $('#rightdocinfo');
if ($rightdocinfo.length > 0) {
$rightdocinfo.show();
}
}
// Reset state
isAnalyzing = false;
currentAnalyzingAddress = null;
currentAnalyzingElement = null;
currentAnalyzingBadge = null;
isPanelOpen = false; // Đánh dấu panel đã đóng
}
// Panel đã song song với rightdocinfo → không cần MutationObserver nữa
// 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();
if ($('#phanTichPanelBody').hasClass('thinking-mode')) {
updateThinkingGifHeight();
}
}
}, 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');
// Mobile: dùng bottom sheet → để CSS điều khiển, bỏ qua reposition bằng JS
if ($(window).width() <= 768) {
return;
}
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'
});
} else {
}
// Restore trạng thái hidden nếu cần
if (wasHidden) {
$reference.hide().css('visibility', '');
}
}
}
// Hiệu ứng typing giả lập đang phân tích trong panel
function stopThinkingTyping() {
typingCancelled = true;
if (typingTimerId) {
clearTimeout(typingTimerId);
typingTimerId = null;
}
// Dừng trình chiếu ảnh khi dừng typing
stopThinkingImages();
}
// Helper GIF: chọn chỉ số ảnh mới 1..10 khác với exclude
function randomGifIndex(exclude) {
let n = exclude;
while (n === exclude) {
n = Math.floor(Math.random() * 10) + 1;
}
return n;
}
// Helper GIF: preload rồi gán src cho img, gọi callback sau khi load xong (hoặc lỗi)
function setGifSrc($img, idx, cb) {
const url = '/assets/images/gif/researching-' + idx + '.gif';
const updateWrapHeight = function(nW, nH){
try {
const $wrap = $img.closest('#thinkingGifWrapper');
if ($wrap.length && nW && nH) {
const wrapW = $wrap.width();
const maxW = wrapW * 0.9; // khớp với CSS max-width:90%
const displayW = Math.min(nW, maxW);
const displayH = nH * (displayW / nW);
$wrap.css('height', displayH + 'px');
}
} catch(e) { /* ignore */ }
};
if ($img.attr('src') === url) {
// Ảnh trùng src -> vẫn cập nhật lại chiều cao wrapper theo kích thước hiển thị hiện tại
const el = $img[0];
if (el && el.naturalWidth && el.naturalHeight) {
updateWrapHeight(el.naturalWidth, el.naturalHeight);
}
if (cb) cb();
return;
}
const pre = new Image();
pre.onload = function() {
$img.attr('src', url);
updateWrapHeight(pre.naturalWidth, pre.naturalHeight);
if (cb) cb();
};
pre.onerror = function() {
$img.attr('src', url);
// Không lấy được kích thước tự nhiên -> để auto
const $wrap = $img.closest('#thinkingGifWrapper');
if ($wrap.length) { $wrap.css('height', 'auto'); }
if (cb) cb();
};
pre.src = url;
}
function updateThinkingGifHeight() {
const $wrap = $('#thinkingGifWrapper');
if ($wrap.length === 0) return;
const $show = $('#thinkingGifA.visible, #thinkingGifB.visible').first();
if ($show.length === 0) return;
const el = $show[0];
if (!el.naturalWidth || !el.naturalHeight) return;
const wrapW = $wrap.width();
const maxW = wrapW * 0.9;
const displayW = Math.min(el.naturalWidth, maxW);
const displayH = el.naturalHeight * (displayW / el.naturalWidth);
$wrap.css('height', displayH + 'px');
}
function startThinkingImages() {
// Nếu body/khung chưa sẵn sàng thì bỏ qua
const $wrap = $('#thinkingGifWrapper');
if ($wrap.length === 0) return;
// Clear trước nếu đang chạy
stopThinkingImages();
thinkingGifActive = true;
const $a = $('#thinkingGifA');
const $b = $('#thinkingGifB');
$a.removeClass('visible');
$b.removeClass('visible');
// Ảnh đầu tiên
thinkingGifCurrent = randomGifIndex(0);
let useA = true; // ảnh A hiển thị trước
setGifSrc($a, thinkingGifCurrent, function(){ $a.addClass('visible'); });
// Mỗi 3s đổi ảnh, crossfade 0.5s qua CSS
thinkingGifIntervalId = setInterval(function(){
if (!thinkingGifActive) return;
const nextIdx = randomGifIndex(thinkingGifCurrent);
const $show = useA ? $b : $a; // show ảnh còn lại
const $hide = useA ? $a : $b;
setGifSrc($show, nextIdx, function(){
// Bắt đầu chuyển ảnh: ẩn ảnh cũ, hiện ảnh mới
$hide.removeClass('visible');
setTimeout(function(){ $show.addClass('visible'); }, 10);
thinkingGifCurrent = nextIdx;
useA = !useA;
});
}, 5000);
}
function stopThinkingImages() {
thinkingGifActive = false;
if (thinkingGifIntervalId) {
clearInterval(thinkingGifIntervalId);
thinkingGifIntervalId = null;
}
}
// Giải quyết address: nếu không có '_' thì decrypt (ưu tiên API, fallback client), ngược lại trả về nguyên vẹn
function clientDecrypt(encrypted, key) {
try {
const bin = atob(encrypted);
let out = '';
for (let i = 0; i < bin.length; i++) {
const ch = bin.charCodeAt(i);
const k = key.charCodeAt(i % key.length);
out += String.fromCharCode(ch ^ k);
}
// Chuẩn hóa tương tự server
out = out.toLowerCase().replace(/[^a-z0-9_]/g, '');
return out || encrypted;
} catch (e) {
return encrypted;
}
}
function resolveAddress(address) {
return new Promise(function(resolve) {
if (!address) { resolve(''); return; }
const addr = String(address);
const lower = addr.toLowerCase();
if (lower === 'trichyeu' || lower === 'cancu' || addr.indexOf('_') !== -1) {
resolve(addr);
return;
}
const randomServer = Math.floor(Math.random() * 10) + 1;
$.ajax({
url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/ajax/decrypt.ndsh.address.php',
type: 'POST',
data: { address_encrypted: addr },
timeout: 10000,
success: function(resp) {
try {
// jQuery sẽ parse JSON theo header, nhưng vẫn fallback nếu là string
if (typeof resp === 'string') { resp = JSON.parse(resp); }
} catch(e) { /* ignore */ }
if (resp && resp.ok && resp.address) {
resolve(resp.address);
} else {
// Fallback client decrypt
resolve(clientDecrypt(addr, 'htpl_noi_dung_vb_address'));
}
},
error: function() {
// Fallback client decrypt
resolve(clientDecrypt(addr, 'htpl_noi_dung_vb_address'));
}
});
});
}
function startThinkingTyping(address) {
// Reset trước khi bắt đầu
stopThinkingTyping();
typingCancelled = false;
const $body = $('#phanTichPanelBody');
if ($body.length === 0) return;
// Đánh dấu chế độ thinking để căn giữa toàn bộ nội dung trong body
$body.addClass('thinking-mode');
// Khởi tạo container nếu chưa có
if ($('#thinkingContainer').length === 0) {
$body.html('');
}
$('#thinkingText').html('');
// Khởi động slideshow ảnh thinking
startThinkingImages();
// Chờ resolve address (decrypt nếu cần) rồi mới bắt đầu typing
resolveAddress(address).then(function(addrPlain) {
if (typingCancelled) return;
const displayNameLarge = getElementDisplayNameLargeFirst(addrPlain);
$('.processing-text').text('Đang xử lý phân tích ' + displayNameLarge.toLowerCase() + '...');
// Câu nói đa dạng cho từng bước
const variants = [
[
'Tôi đã nhận được yêu cầu phân tích {name}...',
'Cảm ơn bạn đã gửi yêu cầu phân tích {name}, tôi sẽ bắt đầu...',
'Bạn đã yêu cầu tôi phân tích {name}, hãy chờ tôi lập kế hoạch...',
'Yêu cầu phân tích {name} đã được ghi nhận, tôi đang chuẩn bị...'
],
[
'Tiếp theo, tôi sẽ đọc kỹ nội dung chi tiết của {name}...',
'Bây giờ tôi cần xem xét kỹ nội dung của {name}...',
'Đang mở và duyệt qua nội dung {name}...'
],
[
'Tôi đã đọc xong. Tôi sẽ kiểm tra xem {name} có bị sửa đổi, bổ sung, thay thế hoặc bãi bỏ bởi điều khoản nào không...',
'Tôi sẽ đối chiếu các văn bản để xem {name} có thay đổi hiệu lực nào không...',
'Tiếp tục kiểm tra trạng thái hiệu lực và các lần sửa đổi của {name}...'
],
[
'Tôi cũng cần xem {name} có được hướng dẫn bởi điều luật nào không...',
'Đang tìm các quy định hướng dẫn áp dụng liên quan đến {name}...',
'Kiểm tra các văn bản hướng dẫn có nhắc đến {name}...'
],
[
'Tôi sẽ kiểm tra {name} có viện dẫn/nhắc đến điều luật khác để tham chiếu hay không...',
'Đang rà soát các điều khoản được {name} đề cập đến...',
'Tìm các tham chiếu pháp lý xuất hiện trong {name}...'
],
[
'Tôi sẽ nghiên cứu về phạm vi điều chỉnh và đối tượng áp dụng'
],
[
'Bây giờ tôi cần tìm ví dụ minh họa cho nội dung điều này...'
],
[
'Tôi cũng cần bổ sung vài lưu ý thực tiễn trong bài phân tích của tôi...'
],
[
'Giờ tôi sẽ viết phần kết luận của bài phân tích...'
],
[
'Bây giờ tôi bắt đầu phân tích chi tiết {name}...',
'Bắt đầu tổng hợp và phân tích {name}...',
'Tiến hành phân tích nội dung {name}...'
]
];
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
const lines = variants.map(group => pick(group).replace(/\{name\}/g, displayNameLarge));
let lineIndex = 0;
let charIndex = 0;
const speedMin = 12; // ms
const speedMax = 25; // ms
const linePause = 2000; // ms chờ 2s giữa các câu
function typeNextChar() {
if (typingCancelled) return;
const line = lines[lineIndex];
if (charIndex < line.length) {
$('#thinkingText').append(line.charAt(charIndex));
charIndex++;
const delay = Math.floor(Math.random() * (speedMax - speedMin + 1)) + speedMin;
typingTimerId = setTimeout(typeNextChar, delay);
} else {
// Hoàn tất 1 câu
if (lineIndex < lines.length - 1) {
// Chờ 2s rồi chuyển sang câu tiếp theo, thay thế câu cũ (không append)
typingTimerId = setTimeout(function() {
if (typingCancelled) return;
$('#thinkingText').html('');
lineIndex++;
charIndex = 0;
typeNextChar();
}, linePause);
} else {
// Câu cuối cùng -> giữ nguyên, chỉ để caret nhấp nháy; không loop
return;
}
}
}
typeNextChar();
});
}
function openPhanTichPanel(address, vbID) {
// Kiểm tra nếu đang phân tích element khác
if (isAnalyzing && currentAnalyzingAddress && currentAnalyzingAddress !== address) {
// Giải mã địa chỉ hiện đang phân tích trước khi hiển thị trong modal
resolveAddress(currentAnalyzingAddress).then(function(addrPlain) {
const currentName = getElementDisplayNameLargeFirst(addrPlain);
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) {
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
// ẨN rightdocinfo để tiết kiệm không gian
if ($rightdocinfo.length > 0) {
$rightdocinfo.hide();
}
// XÓA highlight persistent của TẤT CẢ elements cũ trước
$('#tab_noi_dung_vb .highlight-border-persistent').removeClass('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;
// 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
// Đả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 debugHTML = (memberID === 3 || memberID === 4) ? `
Debug Mode
` : '';
const panelHTML = `
`;
// 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;
// Bắt đầu typing
stopThinkingTyping();
startThinkingTyping(address);
}, 10);
} else {
// Khởi tạo giao diện typing khi mở lại panel
$('#phanTichPanelBody').addClass('thinking-mode').html('');
// Update dimensions khi re-open
updatePanelDimensions();
$('#phanTichPanel').addClass('show');
isPanelOpen = true;
// Bắt đầu typing
stopThinkingTyping();
startThinkingTyping(address);
}
// 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');
// Show typing trong panel thay cho loading
$('#phanTichPanelBody').addClass('thinking-mode').html('');
stopThinkingTyping();
startThinkingTyping(address);
// Gọi API xóa cache trước
deletePhanTichCache(address, vbID, function(deleteSuccess) {
if (deleteSuccess) {
// 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 {
$('#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, attempt) {
attempt = attempt || 1;
const randomServer = Math.floor(Math.random() * 10) + 1;
const debugMode = $('#debugModePhanTich').is(':checked') ? 1 : 0;
$.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,
debug: debugMode
}),
success: function(response) {
if (response && response.ok) {
// Thành công -> kết thúc thinking và reset trạng thái
stopThinkingTyping();
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
}
isAnalyzing = false;
// Render kết quả phân tích với hiệu ứng xuất hiện dần từ trên xuống dưới
let html = '';
html += '';
html += '';
html += '
' + markdownToHtml(response.phan_tich) + '
';
// Khuyến cáo thay cho thống kê token
html += '
';
html += 'Những thông tin em vừa cung cấp chỉ mang tính chất tham khảo, không đại diện cho tư vấn chính thức của luật sư. Quý khách nên tìm đến sự tư vấn trực tiếp từ Luật sư hoặc đơn vị pháp lý có chuyên môn để được hỗ trợ cụ thể cho trường hợp của mình.';
html += '
';
html += '
';
$('#phanTichPanelBody').removeClass('thinking-mode').html(html);
applyFadeReveal();
} else {
// Không ok -> nếu là quá tải và chưa vượt số lần thử thì retry
const msg = response && response.error ? response.error : '';
if (isOverloadedMessage(msg) && attempt < 50 && isPanelOpen && isAnalyzing && currentAnalyzingAddress === address) {
const delay = Math.min(1200 + attempt * 100, 5000);
setTimeout(function() { callPhanTichAPI(address, vbID, callback, attempt + 1); }, delay);
return;
}
// Hết số lần thử hoặc không phải quá tải -> hiển thị lỗi
stopThinkingTyping();
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
}
isAnalyzing = false;
if (isOverloadedMessage(msg)) {
$('#phanTichPanelBody').removeClass('thinking-mode').html(`
Hiện tại A.I đang bị quá tải , vui lòng thử lại sau ít phút!
Thử lại
`);
$(document).off('click.tryAgainPanel').on('click.tryAgainPanel', '#btnTryAgainPanel', function() {
openPhanTichPanel(address, vbID);
});
} else {
$('#phanTichPanelBody').removeClass('thinking-mode').html(`
Lỗi! ${escapeHtml(msg || '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) {
// Nếu quá tải và chưa quá 50 lần -> retry, giữ hiệu ứng thinking và trạng thái analyzing
let errorMsg = error;
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMsg = (xhr.responseJSON.error.message || xhr.responseJSON.error) || errorMsg;
} else if (xhr.responseText) {
errorMsg = xhr.responseText;
}
if ((xhr.status === 503 || isOverloadedMessage(errorMsg)) && attempt < 50 && isPanelOpen && isAnalyzing && currentAnalyzingAddress === address) {
const delay = Math.min(1200 + attempt * 100, 5000);
setTimeout(function() { callPhanTichAPI(address, vbID, callback, attempt + 1); }, delay);
return;
}
// Hết số lần thử hoặc lỗi khác -> hiển thị thông báo phù hợp
stopThinkingTyping();
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
}
isAnalyzing = false;
if (xhr.status === 503 || isOverloadedMessage(errorMsg)) {
$('#phanTichPanelBody').removeClass('thinking-mode').html(`
Hiện tại A.I đang bị quá tải , vui lòng thử lại sau ít phút!
Thử lại
`);
$(document).off('click.tryAgainPanel').on('click.tryAgainPanel', '#btnTryAgainPanel', function() {
openPhanTichPanel(address, vbID);
});
} else {
$('#phanTichPanelBody').removeClass('thinking-mode').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) {
if (callback) callback(response.ok || false);
},
error: function(xhr, status, error) {
if (callback) callback(false);
}
});
}
// Helper: Lấy tên hiển thị của element từ address (có chuyển Telex -> Unicode ở phần giá trị)
function getElementDisplayName(address) {
if (!address) return 'nội dung';
const addrStr = String(address).toLowerCase();
// Các trường hợp đặc biệt không có cặp key_value
if (addrStr === 'trichyeu') return 'Trích yếu';
if (addrStr === 'cancu') return 'Căn cứ';
// Parse địa chỉ linh hoạt: hỗ trợ cả dạng thiếu cặp
const parts = addrStr.split('_');
const types = new Set(['phan', 'chuong', 'muc', 'tieumuc', 'dieu', 'khoan', 'diem']);
const displayParts = [];
for (let i = 0; i < parts.length; i++) {
const key = parts[i];
if (types.has(key)) {
const label = getParentTypeName(key);
const val = (i + 1 < parts.length) ? parts[i + 1] : '';
const valVN = telexToUnicode(val);
displayParts.push(label + (valVN ? ' ' + valVN : ''));
if (val) i++; // bỏ qua value nếu đã dùng
}
}
const title = displayParts.reverse().join(' ');
if (title) return title;
// Fallback: nếu không parse được, trả về address gốc
return address;
}
// Helper: Lấy tên hiển thị theo thứ tự lớn -> nhỏ (Điều > Khoản > Điểm), có chuyển Telex
function getElementDisplayNameLargeFirst(address) {
if (!address) return 'nội dung';
const addrStr = String(address).toLowerCase();
if (addrStr === 'trichyeu') return 'Trích yếu';
if (addrStr === 'cancu') return 'Căn cứ';
const parts = addrStr.split('_');
const types = new Set(['phan', 'chuong', 'muc', 'tieumuc', 'dieu', 'khoan', 'diem']);
const displayParts = [];
for (let i = 0; i < parts.length; i++) {
const key = parts[i];
if (types.has(key)) {
const label = getParentTypeName(key);
const val = (i + 1 < parts.length) ? parts[i + 1] : '';
const valVN = telexToUnicode(val);
displayParts.push(label + (valVN ? ' ' + valVN : ''));
if (val) i++;
}
}
const title = displayParts.join(' ');
return title || address;
}
// Hiệu ứng typing nhanh cho nội dung kết quả (preview text), sau đó thay bằng HTML đầy đủ
let fastTypingTimerId = null;
function stopFastTypingContent() {
if (fastTypingTimerId) {
clearTimeout(fastTypingTimerId);
fastTypingTimerId = null;
}
}
function stripHtmlToText(html) {
const tmp = document.createElement('div');
tmp.innerHTML = html;
const text = (tmp.textContent || tmp.innerText || '') || '';
return text.replace(/\u00A0/g, ' ');
}
function startFastTypingFinalContent(finalHtml) {
stopThinkingTyping();
stopFastTypingContent();
stopThinkingImages();
const $body = $('#phanTichPanelBody');
if ($body.length === 0) return;
$body.removeClass('thinking-mode');
const previewTextFull = stripHtmlToText(finalHtml).trim();
const maxChars = 800; // giới hạn để không quá lâu
const previewText = previewTextFull.slice(0, maxChars);
$body.html('');
let idx = 0;
const speedMin = 2;
const speedMax = 5;
function typeNext() {
if (idx < previewText.length) {
$('#fastTypingText').append(previewText.charAt(idx));
idx++;
const delay = Math.floor(Math.random() * (speedMax - speedMin + 1)) + speedMin;
fastTypingTimerId = setTimeout(typeNext, delay);
} else {
// Khi gõ xong preview → thay bằng HTML đầy đủ
$body.html(finalHtml);
}
}
typeNext();
}
// Áp dụng hiệu ứng xuất hiện dần từ trên xuống dưới
function applyFadeReveal() {
const $container = $('#phanTichPanelBody .fade-reveal-container');
if (!$container.length) return;
// Lấy các block cấp cao và các phần tử con trong nội dung phân tích
const $blocks = $().add($container.children())
.add($container.find('.phan-tich-content').children());
let delayMs = 0;
const stepMs = 60; // ms giữa các phần tử
$blocks.each(function() {
const $el = $(this);
// Bỏ qua các node text trống
if ($el.prop('nodeType') !== 1) return;
$el.addClass('fade-reveal').css('animation-delay', (delayMs/1000) + 's');
delayMs += stepMs;
});
}
// Nhận diện lỗi quá tải model (503/overloaded) - phạm vi toàn cục
function isOverloadedMessage(msg) {
if (!msg) return false;
const s = String(msg).toLowerCase();
return s.includes('overloaded') || s.includes('unavailable') || s.includes('503');
}
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 với retry tối đa 50 lần khi quá tải
(function requestModal(attempt) {
attempt = attempt || 1;
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 && response.ok) {
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) + '
';
html += '';
html += 'Những thông tin em vừa cung cấp chỉ mang tính chất tham khảo, không đại diện cho tư vấn chính thức của luật sư. Quý khách nên tìm đến sự tư vấn trực tiếp từ Luật sư hoặc đơn vị pháp lý có chuyên môn để được hỗ trợ cụ thể cho trường hợp của mình.';
html += '
';
$('#modalPhanTichBody').html(html);
} else {
const msg = response && response.error ? response.error : '';
if (isOverloadedMessage(msg) && attempt < 50) {
const delay = Math.min(1200 + attempt * 100, 5000);
setTimeout(function(){ requestModal(attempt + 1); }, delay);
return;
}
if (isOverloadedMessage(msg)) {
$('#modalPhanTichBody').html(`
Hiện tại A.I đang bị quá tải , vui lòng thử lại sau ít phút!
Thử lại
`);
$(document).off('click.tryAgainModal').on('click.tryAgainModal', '#btnTryAgainModal', function(){
openPhanTichModal(address, vbID);
});
} else {
$('#modalPhanTichBody').html(`
Lỗi! ${escapeHtml(msg || '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.message || xhr.responseJSON.error) || errorMsg;
} else if (xhr.responseText) {
errorMsg = xhr.responseText;
}
if ((xhr.status === 503 || isOverloadedMessage(errorMsg)) && attempt < 50) {
const delay = Math.min(1200 + attempt * 100, 5000);
setTimeout(function(){ requestModal(attempt + 1); }, delay);
return;
}
if (xhr.status === 503 || isOverloadedMessage(errorMsg)) {
$('#modalPhanTichBody').html(`
Hiện tại A.I đang bị quá tải , vui lòng thử lại sau ít phút!
Thử lại
`);
$(document).off('click.tryAgainModal').on('click.tryAgainModal', '#btnTryAgainModal', function(){
openPhanTichModal(address, vbID);
});
} else {
$('#modalPhanTichBody').html(`
Lỗi! Không thể kết nối đến server phân tích.
Chi tiết: ${escapeHtml(errorMsg)}
`);
}
}
});
})(1);
}
// 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) {
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
});
$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;
// Dùng mousemove để track chính xác element nào đang được hover (hiển thị ngay lập tức)
$(document).on('mousemove', '#tab_noi_dung_vb', function(e) {
// Nếu đang hover vào thuật ngữ TNPL thì KHÔNG hiển thị badge để tránh che và chặn tooltip
if ($(e.target).closest('tnpl').length > 0) {
// Ẩn các badge không ở trạng thái analyzing
$('.badge-phan-tich-container').each(function(){
const $b = $(this);
if (!$b.data('analyzing') && !$b.hasClass('analyzing')) {
$b.css({display:'none'});
}
});
return;
}
// 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;
}
// Element thay đổi → xử lý ngay lập tức (không debounce)
// 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 extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
const $badge = $('');
$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;
});
// 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'});
}
});
}
}, 3);
});
// 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')) {
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);
}
}, 3); // 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')) {
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);
}
}, 3);
});
// 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(), 3);
}
});
// Event delegation cho click badge → mở panel
$(document).on('click', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function(e) {
const $badge = $(this);
// Nếu là khách (chưa đăng nhập) sau thời điểm mở khóa → mở modal đăng nhập/mua gói
if (unlockAllPhanTich && memberID <= 0) {
if (!$badge.hasClass('upgrade-require')) {
$badge.addClass('upgrade-require');
}
// Không chặn sự kiện để handler trong modal.content.php bắt và mở modal
return;
}
// Thành viên → mở panel phân tích
e.preventDefault();
e.stopPropagation();
// Nếu badge đang analyzing thì không cho click
if ($badge.hasClass('analyzing') || $badge.data('analyzing')) {
return;
}
// Lấy address từ data-for attribute
const address = $badge.attr('data-for');
if (address && vbID) {
openPhanTichPanel(address, vbID);
} else {
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) {
// Ẩ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'});
}
});
});
// 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 75/KH-UBND thông tin, tuyên truyền về công tác cải cách hành chính năm 2023 trên địa bàn tỉnh Tiền Giang