ỦY BAN NHÂN DÂN THÀNH PHỐ HỒ CHÍ MINH -------
CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc lập - Tự do - Hạnh phúc ---------------
Số: 3682/QĐ-UBND
Thành phố Hồ Chí Minh, ngày 19 tháng 7 năm 2016
QUYẾT ĐỊNH
PHÊ DUYỆT CHƯƠNG TRÌNH BẢO VỆ TRẺ EM THÀNH PHỐ HỒ CHÍ MINH GIAI ĐOẠN 2016 - 2020
CHỦ TỊCH ỦY BAN NHÂN DÂN THÀNH PHỐ HỒ CHÍ MINH
Căn cứ Luật Tổ chức chính quyền địa phương ngày 19 tháng 06 năm 2015;
Căn cứ Luật Bảo vệ, chăm sóc và giáo dục trẻ em ngày 15 tháng 6 năm 2004;
Căn cứ Quyết định số 2361/QĐ-TTg ngày 22 tháng 12 năm 2015 của Thủ tướng Chính phủ về phê duyệt Chương trình bảo vệ trẻ em giai đoạn 2016 - 2020;
Xét đề nghị của Sở Lao động - Thương binh và Xã hội tại Tờ trình số 11923/TTr-SLĐTBXH-TE ngày 18 tháng 5 năm 2016,
QUYẾT ĐỊNH:
Điều 1. Ban hành kèm theo Quyết định này Chương trình bảo vệ trẻ em thành phố Hồ Chí Minh giai đoạn 2016 - 2020.
Điều 2. Quyết định này có hiệu lực kể từ ngày ký ban hành.
Điều 3. Chánh Văn phòng Ủy ban nhân dân thành phố, Giám Đốc Sở Lao động - Thương binh và Xã hội, Thủ trưởng các Sở, ngành thành phố, Chủ tịch Ủy ban nhân dân các quận, huyện chịu trách nhiệm thi hành Quyết định này./.
Nơi nhận: - Như Điều 3; - Thủ tướng Chính phủ; - Bộ Lao động - Thương binh và Xã hội; - Cục Bảo vệ chăm sóc trẻ em; - Thường trực Thành ủy; - Thường trực HĐND Thành phố; - TTUB: CT, các PCT; - VP Thành ủy và các Ban Thành ủy; - VP Thành ủy và các Ban Thành ủy; - Ủy ban MTTQ VN.TP và các Đoàn thể TP; - VP Đoàn Đại biểu Quốc hội; - VP HĐND. TP; - Các Ban Hội đồng nhân dân TP; - TAND. TP; VKSND. TP; - Các Sở, ngành,Đoàn thể TP; - VPUB: CPVP; các Phòng CV; - Lưu: VT, (VXTh2).170
KT. CHỦ TỊCH PHÓ CHỦ TỊCH Nguyễn Thị Thu
CHƯƠNG TRÌNH
BẢO VỆ TRẺ EM THÀNH PHỐ HỒ CHÍ MINH GIAI ĐOẠN 2016 - 2020 (Ban hành kèm theo Quyết định số 3682/QĐ-UBND ngày 19 tháng 7 năm 2016 của Ủy ban nhân dân thành phố)
Những năm qua, cùng với sự quan tâm đầu tư phát triển về kinh tế, vấn đề đảm bảo an sinh xã hội luôn được Thành phố tập trung chỉ đạo thực hiện như: Chương trình giảm nghèo bền vững; Chương trình chăm sóc sức khỏe ban đầu; Chương trình phổ cập giáo dục các bậc học; Đề án phổ cập giáo dục mầm non cho trẻ em 5 tuổi; Chương trình xây dựng xã nông thôn mới ở các huyện ngoại thành; Chương trình đầu tư xây dựng các khu vui chơi, giải trí cho trẻ em trên địa bàn thành phố, trong đó tập trung đầu tư cho các quận ven, các huyện ngoại thành; Chương trình bảo vệ trẻ em giai đoạn 2011 - 2015; Chương trình Phòng, chống tai nạn thương tích trẻ em; Chương trình xây dựng xã, phường phù hợp với trẻ em; Công tác đấu tranh phòng, chống tệ nạn xã hội, tệ nạn ma túy, mại dâm... được thực hiện thường xuyên, được nhân dân đồng tình hưởng ứng, góp phần xây dựng môi trường xã hội lành mạnh.
Sự đóng góp của toàn xã hội trong công tác bảo vệ - chăm sóc trẻ em thời gian qua đã đạt được một số kết quả nhất định: Tỷ lệ trẻ em có hoàn cảnh đặc biệt và có nguy cơ rơi vào hoàn cảnh đặc biệt còn dưới 4,3%; 90% trẻ em có hoàn cảnh đặc biệt được trợ giúp, chăm sóc để phục hồi, tái hoà nhập và có cơ hội phát triển; 90 % trẻ em khi phát hiện có nguy cơ rơi vào hoàn cảnh đặc biệt được can thiệp để giảm thiểu, loại bỏ nguy cơ rơi vào hoàn cảnh đặc biệt; số trẻ em bị xâm hại giảm 40% so với năm 2011Bên cạnh những thành quả trên, hiện nay, trên địa bàn thành phố có hơn 1,4 triệu trẻ em, trong đó có hơn 18 ngàn trẻ em có hoàn cảnh đặc biệt và hơn 57 ngàn trẻ em có nguy cơ rơi vào hoàn cảnh đặc biệt Trên cơ sở những kết quả đã đạt được và thực trạng Thành phố, thực hiện Quyết định số 2361/QĐ-TTg ngày 22 tháng 12 năm 2015 của Thủ tướng Chính phủ về phê duyệt Chương trình bảo vệ trẻ em giai đoạn 2016 - 2020, Ủy ban nhân dân thành phố xây dựng kế hoạch triển khai thực hiện Chương trình bảo vệ trẻ em thành phố Hồ Chí Minh giai đoạn 2016 - 2020 như sau:
I. MỤC TIÊU
1. Mục tiêu tổng quát:
Mọi trẻ em đều được bảo vệ để giảm thiểu nguy cơ rơi vào hoàn cảnh đặc biệt, chú trọng bảo vệ trẻ em để không bị xâm hại; trẻ em có hoàn cảnh đặc biệt được trợ giúp, chăm sóc để phục hồi, hòa nhập cộng đồng và có cơ hội phát triển.
2. Mục tiêu cụ thể:
2.1. Duy trì tỷ lệ trẻ em có hoàn cảnh đặc biệt và có nguy cơ rơi vào hoàn cảnh đặc biệt trên tổng số trẻ em còn dưới 4,3%, không để tăng số lượng trẻ em bị xâm hại so với số liệu cuối năm 2015.
2.2. 90% trẻ em có hoàn cảnh đặc biệt được can thiệp, trợ giúp, chăm sóc và được tiếp cận ít nhất một trong các loại hình dịch vụ bảo vệ trẻ em để phục hồi, hòa nhập cộng đồng và có cơ hội phát triển.
II. ĐỐI TƯỢNG, PHẠM VI
1. Đối tượng: Trẻ em, ưu tiên trẻ em có hoàn cảnh đặc biệt, trẻ em có nguy cơ rơi vào hoàn cảnh đặc biệt; người chưa thành niên vi phạm pháp luật và có nguy cơ vi phạm pháp luật trên địa bàn Thành phố.
2. Phạm vi thực hiện: Chương trình được thực hiện trên địa bàn toàn Thành phố.
III. NỘI DUNG HOẠT ĐỘNG
1. Truyền thông, giáo dục, vận động xã hội nhằm nâng cao nhận thức, kiến thức và kỹ năng bảo vệ, chăm sóc trẻ em cho chính quyền các cấp, các tổ chức, gia đình, nhà trường, cộng đồng xã hội và bản thân trẻ em:
1.1. Chỉ tiêu: trên 90% gia đình, nhà trường, người dân tại cộng đồng và trẻ em trên 6 tuổi được nâng cao nhận thức về bảo vệ trẻ em.
1.2. Nội dung hoạt động:
(i) Nghiên cứu, xây dựng, biên soạn, phát hành tài liệu truyền thông, sản phẩm truyền thông; phối hợp thực hiện các chuyên đề phóng sự, thời sự, chuyên mục về bảo vệ trẻ em.
(ii) Tiếp tục duy trì, nhân rộng các mô hình truyền thông cộng đồng, trường học. Tổ chức các hình thức truyền thông trực tiếp tại cộng đồng, trong trường học về kiến thức, kỹ năng bảo vệ, chăm sóc trẻ em cho đối tượng được nêu tại mục a; tuyên truyền, giới thiệu các biện pháp phòng ngừa và kịp thời phát hiện các trường hợp nguy cơ xâm hại, bạo lực, bóc lột.
(iii) Lồng ghép với các hội thi tìm hiểu kiến thức về chính sách, pháp luật liên quan đến bảo vệ - chăm sóc trẻ em.
(iv) Tăng cường phối hợp liên ngành để xây dựng tài liệu truyền thông cho đối tượng nêu tại mục 1.1 phần 1.
1.3. Cơ quan thực hiện: Sở Lao động -Thương binh và Xã hội chủ trì, phối hợp với Sở Thông tin và Truyền thông, Sở Giáo dục và Đào tạo, Sở Văn hóa và Thể thao, Sở Y tế, Hội Liên hiệp Phụ nữ thành phố, Thành Đoàn thành phố, các Sở, ban, ngành, cơ quan, tổ chức có liên quan và Ủy ban nhân dân các quận - huyện.
2. Củng cố hệ thống tổ chức, nhân lực và nâng cao năng lực cho đội ngũ cán bộ phụ trách công tác bảo vệ - chăm sóc trẻ em và cộng tác viên bảo vệ - chăm sóc trẻ em:
2.1. Chỉ tiêu:
- 100% quận - huyện, phường - xã - thị trấn bố trí đủ cán bộ phụ trách công tác bảo vệ - chăm sóc trẻ em.
- 90% cán bộ phụ trách công tác bảo vệ - chăm sóc trẻ em tại quận - huyện, phường - xã - thị trấn và 70% cộng tác viên được đào tạo, tập huấn về lĩnh vực được phân công.
- 100% quận - huyện, phường - xã - thị trấn củng cố, kiện toàn và vận hành có hiệu quả Ban Điều hành bảo vệ chăm sóc trẻ em cấp quận - huyện và Ban bảo vệ chăm sóc trẻ em cấp phường - xã - thị trấn.
- 90% cán bộ, người trực tiếp chăm sóc trẻ em tại các cơ sở bảo trợ xã hội công lập và ngoài công lập nuôi dưỡng, chăm sóc trẻ em được tập huấn kiến thức cơ bản về kỹ năng bảo vệ trẻ em.
2.2. Nội dung hoạt động:
(i) Tăng cường công tác phối hợp kiểm tra, giám sát về bố trí cán bộ phụ trách công tác bảo vệ - chăm sóc trẻ em tại quận - huyện, phường - xã - thị trấn.
(ii) Phối hợp xây dựng tài liệu và tổ chức các lớp tập huấn cho các đối tượng nêu tại mục 2.2 phần 2.
(iii) Củng cố, kiện toàn, duy trì và nâng cao hiệu quả hoạt động của Ban Điều hành bảo vệ chăm sóc trẻ em quận - huyện, Ban Bảo vệ chăm sóc trẻ em phường - xã - thị trấn.
2.3. Cơ quan thực hiện: Sở Lao động - Thương binh và Xã hội chủ trì, phối hợp với Sở Nội vụ, các Sở, ngành, tổ chức xã hội có liên quan và Ủy ban nhân dân quận - huyện.
3. Phát triển hệ thống cung cấp dịch vụ bảo vệ trẻ em có đủ điều kiện đáp ứng nhu cầu cần sự bảo vệ của mọi trẻ em:
3.1. Chỉ tiêu:
- Củng cố, kiện toàn và hình thành 05 cơ sở cung cấp dịch vụ, trong đó bao gồm cung cấp dịch vụ bảo vệ trẻ em;
- Tạo điều kiện về cơ sở vật chất đảm bảo hoạt động của các cơ sở cung cấp dịch vụ liên quan đến trẻ em;
- Đảm bảo nguồn lực thực hiện chính sách can thiệp cho trẻ em rơi vào hoàn cảnh đặc biệt và các hỗ trợ khẩn cấp khác.
3.2. Nội dung hoạt động:
(i) Xây dựng, bổ sung, hoàn thiện và cung cấp danh mục hệ thống các dịch vụ bảo vệ trẻ em tại cộng đồng.
(ii) Tiếp tục hoàn thiện, duy trì và nâng cao hiệu quả hoạt động của hệ thống cung cấp dịch vụ bảo vệ - chăm sóc trẻ em gồm: Trung tâm Công tác xã hội trẻ em thành phố, Trung tâm Công tác xã hội Ánh Dương, Trung tâm Công tác xã hội Thanh niên, các Phòng Công tác xã hội trẻ em tại bệnh viện, Văn phòng tư vấn trẻ em cấp quận - huyện, điểm tư vấn cộng đồng, tư vấn trường học và các cơ sở trợ giúp trẻ em khác.
(iii) Củng cố và duy trì hoạt động đường dây nóng tiếp nhận các thông tin về xâm hại, bạo lực, bóc lột, sao nhãng trẻ em; tư vấn hỗ trợ có hiệu quả cho trẻ em, cha mẹ và người chăm sóc trẻ em.
(iv) Thực hiện công tác can thiệp, hỗ trợ cho trẻ em bị xâm hại đảm bảo đúng quy trình; hỗ trợ học văn hóa, học nghề; hỗ trợ khẩn cấp đối với các trường hợp trẻ bị xâm hại tình dục, trẻ em bị xâm hại tình dục dẫn đến mang thai, trẻ em và người chưa thành niên bị tai nạn thương tích để lại di chứng tàn tật hoặc dẫn đến tử vong, trẻ bị đuối nước, trẻ tự tử,...
3.3. Cơ quan thực hiện: Sở Lao động - Thương binh và Xã hội chủ trì, phối hợp với Sở Giáo dục và Đào Tạo, Sở Y tế, Sở Tài chính, Công an thành phố, các Sở, ngành, tổ chức, đoàn thể có liên quan và Ủy ban nhân dân quận - huyện.
4. Xây dựng, hoàn thiện hệ thống theo dõi, giám sát và đánh giá thực hiện Chương trình:
4.1. Chỉ tiêu:
- Tham gia xây dựng, hoàn thiện và triển khai bộ tiêu chí theo dõi, giám sát, đánh giá Chương trình; công tác thu thập số liệu đạt yêu cầu về tiến độ thời gian, chất lượng và hiệu quả;
- Cơ sở dữ liệu về bảo vệ trẻ em được thiết lập và cập nhập thường xuyên, kịp thời.
4.2. Nội dung hoạt động
(i) Tham gia xây dựng, hoàn thiện và triển khai bộ chỉ tiêu theo dõi đánh giá chương trình quốc gia bảo vệ trẻ em.
(ii) Tiếp nhận phần mềm thu thập thông tin, phương tiện quản lý và kết nối hệ thống thông tin dữ liệu; tổ chức thu thập thông tin và quản lý cơ sở dữ liệu về bảo vệ trẻ em; tổ chức triển khai và thu thập thông tin sổ hộ gia đình, trong đó bao gồm trẻ em.
(iii) Hàng năm, kiểm tra, giám sát tình hình triển khai thực hiện trên địa bàn thành phố; tổ chức sơ kết giữa kỳ vào cuối năm 2018 và cuối kỳ vào cuối năm 2020 để đánh giá kết quả thực hiện Chương trình.
4.3. Cơ quan thực hiện: Sở Lao động -Thương binh và Xã hội chủ trì, phối hợp với Cục Thống kê, Sở Tư pháp, Công an thành phố, Sở Giáo dục và Đào tạo; các Sở, ngành, tổ chức có liên quan và Ủy ban nhân dân quận - huyện.
5. Nâng cao năng lực, tham gia phối hợp đề xuất, kiến nghị hoàn thiện thể chế về bảo vệ trẻ em và người chưa thành niên trong quá trình tố tụng dân sự, hình sự và xử lý vi phạm hành chính:
5.1. Chỉ tiêu:
- 100% Lãnh đạo, chỉ huy Công an các đơn vị địa phương thuộc Công an thành phố được trang bị các kiến thức, kỹ năng cần thiết về hỗ trợ tư pháp đối với người chưa thành niên và thực hiện có hiệu quả công tác bảo vệ quyền và lợi ích hợp pháp của người chưa thành niên trong trong quá trình tố tụng hình sự, dân sự, xử lý vi phạm hành chính.
- 100% thẩm phán, kiểm sát viên trực tiếp phụ trách hoặc được phân công giải quyết xử lý, xét xử các vụ án liên quan đến gia đình và người chưa thành niên được tập huấn kiến thức cần thiết về tâm lý, chính sách pháp luật liên quan đến trẻ em và người chưa thành niên.
- Thực hiện mô hình phòng ngừa, kéo giảm 10% người chưa thành niên vi phạm pháp luật trên địa bàn quận 1 và quận Bình Thạnh.
- 100% người chưa thành niên vi phạm pháp luật được giám sát và trợ giúp pháp lý phù hợp theo quy định; tiếp tục duy trì hoạt động mô hình phòng hỏi cung, ghi lời khai thân thiện.
5.2. Nội dung hoạt động:
(i) Tăng cường nhận thức và nâng cao năng lực bảo vệ quyền và lợi ích hợp pháp của người chưa thành niên trong quá trình tố tụng hình sự, dân sự và xử lý vi phạm hành chính; xây dựng tài liệu, tổ chức các lớp tập huấn, bồi dưỡng nâng cao năng lực, kỹ năng và biện pháp quản lý, giáo dục, bảo vệ và chăm sóc trẻ em và người chưa thành niên vi phạm pháp luật tại cộng đồng dân cư cho các đối tượng tại mục 5.1 phần 5.
(ii) Xây dựng và triển khai các mô hình thí điểm phòng ngừa, quản lý, giáo dục trẻ em vi phạm pháp luật tại cộng đồng;
(iii) Xây dựng 2 mô hình trên địa bàn quận 1 và quận Bình Thạnh (1 quận/1 mô hình) trong công tác phòng ngừa, quản lý, giáo dục người chưa thành niên và người chưa thành niên vi phạm pháp luật tại cộng đồng dân cư, cụ thể:
Thành lập Ban chỉ đạo thực hiện mô hình bao gồm: Lãnh đạo chính quyền địa phương; Công an địa phương (trực tiếp là Cảnh sát khu vực, Công an xây dựng phong trào và phụ trách xã về an ninh trật tự và Công an xã); các ban ngành, tổ chức đoàn thể xã hội; gia đình và nhà trường;
Tổ chức các hoạt động tuyên truyền nâng cao về nhận thức và kỹ năng cho cán bộ Công an và cán bộ tư pháp địa phương trong công tác bảo vệ, chăm sóc, quản lý, giáo dục, phòng ngừa người chưa thành niên nói chung, người chưa thành niên làm trái pháp luật và người chưa thành niên có nguy cơ làm trái pháp luật tại địa bàn cơ sở;
Tiến hành rà soát phân loại số người chưa thành niên và người chưa thành niên vi phạm pháp luật và số người chưa thành niên có nguy cơ vi phạm pháp luật trong phạm vi hoạt động của mô hình; bàn giao số người chưa thành niên vi phạm pháp luật và có nguy cơ vi phạm pháp luật cho các thành viên trong Ban chỉ đạo để có biện pháp phối hợp trong công tác quản lý, giáo dục;
Trang bị phương tiện hỗ trợ Ban chỉ đạo thực hiện công việc có hiệu quả góp phần nâng cao hiệu quả hoạt động của mô hình;
Xây dựng mô hình hỗ trợ người chưa thành niên vi phạm pháp luật tái hòa nhập cộng đồng sau khi chấp hành xong hình phạt tù, biện pháp xử lý hành chính bằng các biện pháp hỗ trợ học văn hóa, giới thiệu học nghề, việc làm...
iv) Hỗ trợ thành lập mới; duy trì, củng cố hoạt động mô hình phòng hỏi cung, ghi lời khai thân thiện đối với người chưa thành niên đã thành lập trong đó bao gồm hỗ trợ phương tiện kỹ thuật, tài liệu,...
(v) Đẩy mạnh hoạt động của Tòa án gia đình và người chưa thành niên.
5.3. Cơ quan thực hiện:
- Sở Tư pháp chủ trì, phối hợp với các Sở, ngành và đơn vị có liên quan thực hiện hoạt động (i) và (ii) mục 5.2 phần 5.
- Sở Lao động - Thương binh và Xã hội chủ trì, phối hợp với các Sở, ngành và đơn vị liên quan thực hiện hoạt động (iii) mục 5.2 phần 5.
- Công an Thành phố chủ trì, phối hợp với các Sở, ngành và đơn vị có liên quan thực hiện hoạt động (iv) mục 5.2 phần 5.
- Đề nghị Tòa án nhân dân thành phố chủ trì, phối hợp với các Sở, ngành và đơn vị liên quan thực hiện hoạt động (v) mục 5.2 phần 5.
IV. NHIỆM VỤ VÀ GIẢI PHÁP:
1. Tăng cường sự lãnh đạo của các cấp ủy Đảng, chính quyền đối với công tác bảo vệ trẻ em. Nâng cao hiệu quả hoạt động và điều hành của Ban điều hành bảo vệ trẻ em các cấp; bố trí đủ nhân lực, kinh phí và các điều kiện cần thiết khác cho việc thực hiện công tác bảo vệ trẻ em. Đưa các mục tiêu bảo vệ trẻ em vào Kế hoạch phát triển kinh tế - xã hội giai đoạn 5 năm và hàng năm của Thành phố. Duy trì việc thực hiện hiệu quả cơ chế báo cáo, thông tin tới các cấp về công tác bảo vệ trẻ em.
2. Đẩy mạnh thông tin, truyền thông, giáo dục, vận động xã hội nhằm nâng cao nhận thức, thay đổi hành vi về bảo vệ trẻ em của chính quyền các cấp, các tổ chức, gia đình, nhà trường, cộng đồng xã hội và trẻ em.
3. Tăng cường công tác thanh tra, kiểm tra, đánh giá kết quả thực hiện nhiệm vụ bảo vệ, chăm sóc trẻ em hàng năm, giữa kỳ và cuối kỳ; phát hiện, xử lý kịp thời các hành vi vi phạm quyền trẻ em.
4. Huy động sự tham gia của các cơ quan, Ủy ban Mặt trận Tổ quốc Việt Nam thành phố và các đoàn thể chính trị - xã hội, các tổ chức xã hội, các đơn vị thực hiện Chương trình.
5. Tăng cường hợp tác quốc tế nhằm tranh thủ nguồn lực, kinh nghiệm về bảo vệ trẻ em.
6. Lồng ghép các chương trình, đề án liên quan đến lĩnh vực bảo vệ - chăm sóc trẻ em trên địa bàn thành phố để đạt được mục tiêu của Chương trình bảo vệ trẻ em.
V. TỔ CHỨC THỰC HIỆN
1. Sở Lao động - Thương binh và Xã hội:
Chủ trì, phối hợp với các Sở, ngành, đoàn thể, Ủy ban nhân dân các quận - huyện và các tổ chức có liên quan triển khai thực hiện, dự trù kinh phí hàng năm và điều phối các hoạt động của Chương trình; chủ trì quản lý và tổ chức thực hiện các hoạt động đã được phân công trong Chương trình theo quy định hiện hành; hướng dẫn, kiểm tra, tổng hợp tình hình thực hiện Chương trình và định kỳ báo cáo Ủy ban nhân dân thành phố; tham mưu tổ chức Hội nghị sơ kết vào cuối năm 2018 và Hội nghị tổng kết vào cuối năm 2020.
2. Sở Giáo dục và Đào tạo:
Triển khai xây dựng môi trường học tập lành mạnh, không để xảy ra bạo lực học đường; tiếp tục triển khai có hiệu quả phong trào thi đua “Xây dựng trường học thân thiện, học sinh tích cực”; bồi dưỡng, nâng cao nhận thức, năng lực về bảo vệ trẻ em cho cán bộ quản lý, giáo viên, cán bộ phụ trách công tác Đoàn - Đội; giáo dục kỹ năng sống, kỹ năng tự bảo vệ, kỹ năng giao tiếp, ứng xử tích cực cho học sinh lồng ghép vào chương trình giáo dục trong nhà trường và các cơ sở giáo dục.
3. Sở Văn hóa và Thể thao:
Chủ trì, phối hợp với Sở Lao động - Thương binh và Xã hội nghiên cứu, đề xuất chính sách bảo vệ trẻ em trong các hoạt động văn hóa - thể thao; tăng cường thanh tra, kiểm tra và quản lý chặt chẽ các sản phẩm văn hóa, dịch vụ vui chơi, giải trí dành cho trẻ em, đảm bảo cho trẻ em được tiếp cận môi trường văn hóa lành mạnh.
4. Sở Du lịch:
Chủ trì, phối hợp với Sở Lao động - Thương binh và Xã hội nghiên cứu, đề xuất chính sách bảo vệ trẻ em trong các hoạt động du lịch trên địa bàn thành phố.
5. Sở Tư pháp:
Tăng cường hướng dẫn, thường xuyên kiểm tra đối với tổ chức thực hiện hoạt động trợ giúp pháp lý cho trẻ em; tăng cường thực hiện chức năng quản lý nhà nước về công tác nuôi con nuôi; đề xuất hình thức, mức xử lý nặng những trường hợp vi phạm; đẩy mạnh tuyên truyền, phổ biến, giáo dục pháp luật liên quan đến bảo vệ - chăm sóc trẻ em; tổ chức nâng cao năng lực; đề xuất, kiến nghị hoàn thiện thể chế về bảo vệ trẻ em trong quá trình tố tụng và xử lý vi phạm hành chính; chủ trì quản lý và tổ chức thực hiện các nội dung hoạt động đã được phân công trong Chương trình theo quy định hiện hành.
6. Sở Y tế:
Chủ trì, phối hợp với Sở Lao động - Thương binh và Xã hội và các Sở, ngành có liên quan hướng dẫn về chăm sóc và hỗ trợ trẻ em bị xâm hại, bạo lực, trẻ em có hoàn cảnh đặc biệt.
7. Sở Tài chính:
Thẩm định và bố trí kinh phí trong dự toán chi ngân sách hàng năm cho các Sở, ngành, tổ chức đoàn thể, quận - huyện được giao nhiệm vụ triển khai thực hiện Chương trình; thanh tra, kiểm tra việc quản lý, sử dụng kinh phí thực hiện Chương trình.
8. Sở Kế hoạch và Đầu tư:
Chủ trì, phối hợp với Sở Tài chính, Sở Lao động - Thương binh và Xã hội và các Sở, ngành liên quan vận động các nguồn hỗ trợ phát triển chính thức (ODA) cho các chương trình, dự án về bảo vệ - chăm sóc trẻ em.
9. Công an thành phố:
Xây dựng và thực hiện Kế hoạch về đấu tranh, phòng ngừa tội phạm xâm hại trẻ em, tội phạm trong lứa tuổi trẻ em; tiếp tục đổi mới, nâng cao hiệu quả việc quản lý, giáo dục trẻ em vi phạm pháp luật; xây dựng và áp dụng quy trình điều tra thân thiện với trẻ em vi phạm pháp luật; phối hợp với các đơn vị thực hiện các nội dung hoạt động được phân công trong Chương trình triển khai đạt hiệu quả các mục tiêu đề ra.
10. Sở Thông tin và Truyền thông:
Chỉ đạo các cơ quan báo, đài thành phố mở các chuyên trang, chuyên mục, các chương trình phát thanh, truyền hình với nhiều hình thức phong phú đa dạng, nội dung phù hợp để vận động xã hội nâng cao nhận thức và trách nhiệm bảo vệ trẻ em.
11. Sở Nội vụ:
Chủ trì, phối hợp với Sở Lao động - Thương binh và Xã hội và các cơ quan liên quan hướng dẫn các Sở, ngành, quận - huyện bố trí hợp lý biên chế nhân sự phụ trách công tác bảo vệ - chăm sóc trẻ em.
12. Ủy ban nhân dân quận - huyện:
Tổ chức triển khai thực hiện Chương trình tại địa phương; xây dựng và tổ chức thực hiện các kế hoạch hoạt động hàng năm về bảo vệ - chăm sóc trẻ em phù hợp với Chương trình này và Kế hoạch phát triển kinh tế - xã hội của địa phương trong cùng thời kỳ; lồng ghép việc thực hiện có hiệu quả Chương trình này với các chương trình khác có liên quan trên địa bàn; đẩy mạnh phối hợp liên ngành trong thực hiện nhiệm vụ bảo vệ và chăm sóc trẻ em; tiếp tục xây dựng xã - phường phù hợp với trẻ em; chủ động bố trí ngân sách, nhân lực để thực hiện Chương trình; thường xuyên kiểm tra việc thực hiện Chương trình tại địa phương; thực hiện chế độ báo cáo hàng năm, sơ kết, tổng kết việc thực hiện Chương trình trên địa bàn theo quy định hiện hành.
13. Đề nghị Tòa án nhân dân thành phố, Viện kiểm sát nhân dân thành phố: trong phạm vi, chức năng của đơn vị chủ trì quản lý, tổ chức triển khai thực hiện các hoạt động đã được phân công trong Chương trình theo quy định hiện hành.
14. Đề nghị Ủy ban Mặt trận Tổ quốc Việt Nam thành phố và các tổ chức xã hội thành viên, Hội Liên hiệp phụ nữ thành phố, Thành Đoàn thành phố, Hội Bảo trợ trẻ em thành phố, Hội Bảo vệ quyền trẻ em thành phố, trong phạm vi chức năng, nhiệm vụ của mình, tổ chức triển khai Chương trình hàng năm; đẩy mạnh công tác tuyên truyền, giáo dục nhằm nâng cao nhận thức về bảo vệ - chăm sóc trẻ em trong tổ chức mình; tham gia xây dựng, đề xuất, kiến nghị bổ sung, điều chỉnh chính sách, pháp luật, quản lý nhà nước, giám sát việc thực hiện pháp luật về bảo vệ - chăm sóc và giáo dục trẻ em.
VI. KINH PHÍ DỰ KIẾN
Kinh phí thực hiện Chương trình bảo vệ trẻ em thành phố Hồ Chí Minh giai đoạn 2016 - 2020 gồm:
- Ngân sách Trung ương (nếu có);
- Ngân sách địa phương;
- Huy động từ các nguồn lực hỗ trợ khác.
Kinh phí thực hiện kế hoạch phòng, chống tai nạn thương tích trẻ em được bố trí trong dự toán ngân sách giao hàng năm cho các cơ quan đơn vị. Hàng năm, các cơ quan đơn vị lập dự toán chi tiết gửi Sở Tài chính thẩm định và trình Ủy ban nhân dân Thành phố bố trí kinh phí cùng với kỳ lập dự toán kinh phí hoạt động của cơ quan đơn vị./.
lồng nhau (bên trong) hay không
const memberID = 0;
const isVIP = false;
const vbID = '4216fed2d873a67c0331712e57f7888f';
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
// Detect touch device - chỉ true khi thiết bị CHÍNH sử dụng touch (không có mouse chính xác)
const isTouchDevice = () => {
// Nếu USE_THREE_DOTS_BUTTON = true, luôn trả về true (hiện trên mọi thiết bị)
if (USE_THREE_DOTS_BUTTON === true) return true;
// Ưu tiên: Kiểm tra pointer: coarse (thiết bị chính sử dụng touch, không có mouse/trackpad)
if (window.matchMedia) {
// pointer: coarse = thiết bị chính sử dụng touch (mobile/tablet)
// pointer: fine = thiết bị có mouse/trackpad chính xác (desktop/laptop)
const hasCoarsePointer = window.matchMedia('(pointer: coarse)').matches;
if (hasCoarsePointer) return true;
}
// Fallback: Kiểm tra touch support (không chính xác lắm vì laptop cũng có thể có touch)
// Chỉ dùng khi không support matchMedia
if (!window.matchMedia) {
return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
}
return false;
};
const isTouch = isTouchDevice();
// State for dropdown menu on touch devices
let currentOpenDropdown = null;
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: '2016-07-19 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/menu
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/menu trực tiếp
const $parent = $element.closest('phan, chuong, muc, tieumuc, dieu, khoan, diem');
if ($parent.length > 0) {
const address = $parent.attr('address');
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
const extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
if (isTouch) {
// Touch device: Thêm nút 3 chấm (append vào body)
if ($('body').find('.menu-button-phan-tich[data-for="' + address + '"]').length === 0) {
const $menuButton = $('');
$('body').append($menuButton); // Append vào body
$parent.addClass('has-phan-tich-menu');
// Trigger update positions sau khi thêm
setTimeout(function() {
if (typeof window.updateMenuButtonPositions === 'function') {
window.updateMenuButtonPositions();
}
}, 10);
}
} else {
// Desktop: Append badge vào parent
if ($parent.find('.badge-phan-tich[data-for="' + address + '"]').length === 0) {
$element.attr('data-address', address);
const $badge = $('');
$parent.append($badge);
$parent.addClass('has-phan-tich-badge');
}
}
}
// Xử lý các p con (nếu có sub-p)
attachPhanTichBadge($element);
}, 3); // Đợi 3ms để 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');
// Trên touch device: Thêm nút 3 chấm dọc (append vào body vì dùng fixed position)
if (isTouch) {
// Kiểm tra đã có nút 3 chấm chưa (trong body)
if ($('body').find('.menu-button-phan-tich[data-for="' + address + '"]').length === 0) {
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
const extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
// Tạo nút 3 chấm với dropdown và append vào body
const $menuButton = $('');
$('body').append($menuButton); // Append vào body, không vào parent
$parent.addClass('has-phan-tich-menu');
}
} else {
// Desktop: Giữ nguyên badge hover như cũ (append vào parent)
if ($parent.find('.badge-phan-tich[data-for="' + address + '"]').length === 0) {
$p.attr('data-address', address);
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
const extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
const $badge = $('');
$parent.append($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 += 'Nội dung phân tích này chỉ mang tính chất tham khảo, để hiểu rõ hơn, quý khách nên tham vấn ý kiến luật sư và các chuyên gia 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 += 'Nội dung phân tích này chỉ mang tính chất tham khảo, để hiểu rõ hơn, quý khách nên tham vấn ý kiến luật sư và các chuyên gia 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 + 8) + 'px',
left: (offset.left + $parent.outerWidth() - badgeWidth - scrollLeft - 4) + '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) {
// Bỏ logic ẩn badge khi hover vào tnpl - bây giờ badge luôn hiển thị
// Badge "Phân tích" sẽ luôn hiện kể cả khi di chuột vào tnpl
// Tìm element gần nhất (phan, chuong, muc, tieumuc, 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) {
// Nếu di chuột sang menu button thì KHÔNG clear currentHoveredElement
if (e.relatedTarget && $(e.relatedTarget).closest('.menu-button-phan-tich').length > 0) {
return;
}
// 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');
// Nếu di chuột sang menu button của chính nó thì KHÔNG xử lý mouseleave
if (e.relatedTarget && $(e.relatedTarget).closest('.menu-button-phan-tich[data-for="' + parentAddress + '"]').length > 0) {
return;
}
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 (typeof memberID !== 'undefined' && memberID !== 4 && !isVIP) {
e.preventDefault();
e.stopPropagation();
openModal(this, '/ajax/member/m-register/new/1');
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!');
}
});
// Xử lý click vào CTTD/DCTD
// Xử lý click vào badge "Hướng dẫn" (.huong-dan-badge) -> coi như click vào CTTD
$(document).on('click', '.huong-dan-badge', function(e) {
e.preventDefault();
e.stopPropagation();
var $el = $(this);
// 1. Tìm trong container gần nhất
var $cttd = $el.closest('p, div, li, td, .list-item').find('cttd, dctk, dctd, .chuthichtudong').first();
// 2. Nếu không thấy, tìm trong các sibling
if ($cttd.length === 0) {
$cttd = $el.siblings('cttd, dctk, dctd, .chuthichtudong').first();
}
// 3. Nếu vẫn không thấy, thử tìm ở paragraph liền trước (trường hợp badge nằm ở dòng sau)
if ($cttd.length === 0) {
$cttd = $el.closest('p, div').prev().find('cttd, dctk, dctd, .chuthichtudong').last();
}
if ($cttd.length > 0) {
// Ưu tiên click vào span bên trong nếu có (cho desktop handler trong dan.chieu.buble.v.3.php)
var $span = $cttd.find('span').first();
if ($span.length > 0) {
$span[0].click();
} else {
// Fallback click vào chính thẻ đó (cho mobile hoặc nếu không có span)
$cttd[0].click();
}
} else {
console.warn('Không tìm thấy thẻ CTTD tương ứng cho badge hướng dẫn');
}
});
$(document).on('click', 'cttd, dctk, dctd, .chuthichtudong', function(e) {
// Khách (non-VIP): mở modal đăng ký
if (typeof memberID !== 'undefined' && memberID !== 4 && !isVIP) {
e.preventDefault();
e.stopImmediatePropagation();
openModal(this, '/ajax/member/m-register/new/1');
return false;
}
// VIP: Đảm bảo các thuộc tính kích hoạt modal có sẵn
var $this = $(this);
if (!$this.attr('data-toggle')) {
$this.attr('data-toggle', 'modal');
$this.attr('data-target', '#ct_modal');
}
// Force mở modal #ct_modal an toàn (Logic từ fallback cũ)
var $ctModal = $('#ct_modal');
if ($ctModal.length > 0) {
if (typeof $ctModal.modal === 'function') {
$ctModal.modal('show');
} else if (window.jQuery && typeof window.jQuery('#ct_modal').modal === 'function') {
window.jQuery('#ct_modal').modal('show');
} else {
// Fallback load bootstrap if missing
console.warn('Bootstrap modal not loaded. Attempting to load local fallback...');
var loadBootstrap = function() {
$.getScript('/libs/jquery/bootstrap/dist/js/bootstrap.js', function() {
if (typeof $('#ct_modal').modal === 'function') {
$('#ct_modal').modal('show');
} else if (window.jQuery && typeof window.jQuery('#ct_modal').modal === 'function') {
window.jQuery('#ct_modal').modal('show');
}
});
};
if (typeof window.Tether === 'undefined') {
$.getScript('https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js', loadBootstrap);
} else {
loadBootstrap();
}
}
}
});
// Ẩ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);
// Function để update vị trí nút 3 chấm (fixed position) - exposed globally
window.updateMenuButtonPositions = function() {
if (!isTouch) return; // Chỉ chạy trên touch device
$('.menu-button-phan-tich').each(function() {
const $menuButton = $(this);
const address = $menuButton.attr('data-for');
const $parent = $('[address="' + address + '"]').first();
if ($parent.length > 0) {
const parentOffset = $parent.offset();
const parentWidth = $parent.outerWidth();
const parentHeight = $parent.outerHeight();
const scrollTop = $(window).scrollTop();
const windowHeight = $(window).innerHeight();
const viewportTop = scrollTop;
const viewportBottom = scrollTop + windowHeight;
// Kiểm tra parent có trong viewport không
const parentTop = parentOffset.top;
const parentBottom = parentOffset.top + parentHeight;
const inViewport = (parentBottom > viewportTop && parentTop < viewportBottom);
if (inViewport) {
const scrollLeft = $(window).scrollLeft();
// Tính vị trí: góc phải của parent element
// Canh chỉnh top để tâm của nút 3 chấm (cao ~36px) ngang hàng với tâm của badge (cao ~21px, top 8px)
// Badge center: 8 + 10.5 = 18.5px
// Button center: Top + 18px
// => Top = 18.5 - 18 = 0.5px -> Lấy tròn 1px
const topOffset = 3;
topPosition = parentOffset.top - scrollTop + topOffset;
// Left = left của parent + width của parent - khoảng 30px (chiều rộng icon + padding)
// Để nút nằm bên trong parent, góc phải
// Trừ scrollLeft vì position: fixed tính theo viewport
const leftPosition = parentOffset.left + parentWidth - 2 - scrollLeft;
$menuButton.css({
top: topPosition + 'px',
left: leftPosition + 'px',
right: 'auto', // Reset right
display: 'block'
});
} else {
// Ẩn nếu parent không trong viewport
$menuButton.css({display: 'none'});
}
}
});
};
// Highlight parent khi hover/touch vào nút 3 chấm
$(document).on('mouseenter touchstart', '.menu-button-phan-tich', function() {
const address = $(this).attr('data-for');
const $parent = $('[address="' + address + '"]').first();
if ($parent.length) {
$parent.addClass('highlight-border');
$parent.data('hovering', true); // Mark as hovering
currentHoveredElement = $parent; // Update global tracker
// Attach badge nếu chưa có (logic tương tự như khi hover vào parent)
if ($parent.find('.badge-phan-tich-container[data-for="' + address + '"]').length === 0) {
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
const extraClass = (unlockAllPhanTich && memberID <= 0) ? ' upgrade-require' : '';
const $badge = $('');
$parent.append($badge);
$parent.addClass('has-phan-tich-badge');
}
// Show badge tương ứng
if (typeof showPhanTichBadgeForParent === 'function') {
showPhanTichBadgeForParent($parent);
}
}
});
$(document).on('mouseleave touchend', '.menu-button-phan-tich', function(e) {
const address = $(this).attr('data-for');
const $parent = $('[address="' + address + '"]').first();
// Nếu di chuột sang parent thì không remove highlight
if (e.relatedTarget && $(e.relatedTarget).closest('[address="' + address + '"]').length > 0) {
return;
}
// Nếu di chuột ra ngoài hoàn toàn (không vào parent)
currentHoveredElement = null;
if ($parent.length) {
$parent.removeClass('highlight-border');
$parent.data('hovering', false);
// Hide badge
if (typeof hidePhanTichBadgeForParent === 'function') {
hidePhanTichBadgeForParent($parent);
}
}
});
// ===== Event handlers cho touch device =====
if (isTouch) {
// Update positions khi scroll hoặc resize
$(window).on('scroll resize', function() {
window.updateMenuButtonPositions();
});
// Initial update
setTimeout(window.updateMenuButtonPositions, 500);
// Xử lý click nút Phân tích (badge hoặc dropdown item)
$(document).on('click', '.badge-phan-tich, .dropdown-item-phan-tich[data-action="analyze"]', function(e) {
e.preventDefault();
e.stopPropagation();
if (typeof memberID !== 'undefined' && memberID !== 4 && !isVIP) {
openModal(this, '/ajax/member/m-register/new/1');
return;
}
const $btn = $(this);
let address = $btn.attr('data-for');
// Nếu click từ dropdown item, cần lấy address từ parent menu button
if (!address) {
const $menuBtn = $btn.closest('.menu-button-phan-tich');
address = $menuBtn.attr('data-for');
}
if (address) {
// Đóng dropdown menu nếu đang mở (trên mobile)
if (currentOpenDropdown) {
currentOpenDropdown.removeClass('show');
currentOpenDropdown = null;
}
openPhanTichPanel(address, vbID);
}
});
// Click vào nút 3 chấm -> mở panel phân tích luôn (không cần dropdown)
$(document).on('click', '.btn-three-dots', function(e) {
e.preventDefault();
e.stopPropagation();
const $button = $(this);
const $menuContainer = $button.closest('.menu-button-phan-tich');
const address = $menuContainer.attr('data-for');
// Kiểm tra nếu là khách (chưa đăng nhập)
if (unlockAllPhanTich && memberID <= 0) {
if (!$menuContainer.hasClass('upgrade-require')) {
$menuContainer.addClass('upgrade-require');
}
// Trigger event để modal.content.php bắt và mở modal đăng nhập
$menuContainer.trigger('click');
return;
}
// Thành viên -> mở panel phân tích trực tiếp
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!');
}
});
// Update positions khi scroll hoặc resize
$(window).on('scroll resize', function() {
window.updateMenuButtonPositions();
});
}
}
});
Tra cứu thuật ngữ với từ hoặc cụm từ đã chọn?
×
Quyết định 3682/QĐ-UBND năm 2016 phê duyệt Chương trình bảo vệ trẻ em thành phố Hồ Chí Minh giai đoạn 2016-2020