diff --git a/sisvietnamvn_main/fix_html.py b/sisvietnamvn_main/fix_html.py new file mode 100644 index 00000000..ec6bfd65 --- /dev/null +++ b/sisvietnamvn_main/fix_html.py @@ -0,0 +1,103 @@ +import os +import re + +script_replacement = """ + """ + +files = [ + 'src/main/resources/templates/posts/full-width.html', + 'src/main/resources/templates/posts/livestream.html', + 'src/main/resources/templates/posts/sidebar.html' +] + +for file_path in files: + with open(file_path, 'r') as f: + content = f.read() + + # Regex to match the old Editor.js script block + pattern = re.compile(r' + """ + +file_path = 'src/main/resources/templates/dao-tao-detail.html' +with open(file_path, 'r') as f: + content = f.read() + +# Pattern matches from to the end of the \ No newline at end of file +
TTTên bàiMục tiêu bài họcSố tiết học
Tổn
g số

thuyế
t
Thực hành
LabBuồn
g
bệnh
01Bức xạ tia x- Trình bày được đơn vị đo bức xạ
tia X, thực hiện đúng quy định kỹ
thuật an toàn bức xạ tia X.
- Mô tả chính xác phương pháp đo
bức xạ tia X.
120210
02Nguyên lý tạo hình
ảnh trên dsa và an toàn
bức xạ tia x
- Mô tả được nguyên lý tạo hình
ảnh trên DSA.
- Vận dụng được các nguyên tắc
an toàn bức xạ tia X.
220220
03Thuốc cản quang trong
can thiệp nội mạch
- Phân biệt được các nhóm thuốc
cản quang hiện nay.
- Áp dụng đúng liều lượng thuốc
cản quang trong can thiệp nội
mạch, các phản ứng bất lợi của
thuốc cản quang và xử trí.
220220
04Bệnh thận do thuốc
cản quang
- Trình bày tiêu chuẩn chẩn
đoán của bệnh thận do thuốc cản
quang (CIN)
- Giải thích chính xác cơ chế
bệnh sinh của CIN
Đánh giá được nguy cơ và xây dựng
cách phòng ngừa CIN.
42022020
05Hình ảnh Giải phẫu
học của gan
- Trình bày được giải phẩu các
phân thùy gan, các cấu trúc cố
định gan và liên quan của gan với
các tạng xung quanh.
240420
\ No newline at end of file diff --git a/sisvietnamvn_main/sisvietnam_backup.dmp b/sisvietnamvn_main/sisvietnam_backup.dmp index de2438f1..10af5d30 100644 Binary files a/sisvietnamvn_main/sisvietnam_backup.dmp and b/sisvietnamvn_main/sisvietnam_backup.dmp differ diff --git a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/PostMigrator.java b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/PostMigrator.java index 88b6f998..ccf2c128 100644 --- a/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/PostMigrator.java +++ b/sisvietnamvn_main/src/main/java/com/sisvietnamvn/web/config/PostMigrator.java @@ -1,16 +1,12 @@ package com.sisvietnamvn.web.config; import com.sisvietnamvn.web.domain.Post; -import com.sisvietnamvn.web.domain.PageStatus; import com.sisvietnamvn.web.repository.PostRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import java.util.Optional; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.time.Instant; -import java.time.temporal.ChronoUnit; +import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; @Component public class PostMigrator implements CommandLineRunner { @@ -23,57 +19,110 @@ public class PostMigrator implements CommandLineRunner { @Override public void run(String... args) throws Exception { - String[] slugs = { - "can-thiep-mach-mau-than-kinh-nang-cao", - "can-thiep-mach-mau-cac-tang-va-ngoai-bien-co-ban", - "chuan-bi-dung-cu-va-cham-soc-benh-nhan-trong-phong-chup-mach", - "tim-mach-can-thiep-co-ban" - }; + System.out.println("=== STARTING JSON TO HTML MIGRATION ==="); - String[] titles = { - "Can thiệp mạch máu thần kinh nâng cao", - "Can thiệp mạch máu các tạng và mạch máu ngoại biên cơ bản", - "Chuẩn bị dụng cụ và chăm sóc bệnh nhân trong phòng chụp mạch", - "Tim mạch can thiệp cơ bản" - }; + List posts = postRepository.findAll(); + ObjectMapper mapper = new ObjectMapper(); + int count = 0; - System.out.println("=== STARTING MIGRATION FOR 4 COURSES ==="); - - for (int i = 0; i < slugs.length; i++) { - String slug = slugs[i]; - String title = titles[i]; - String path = "pdf_json_output/" + slug + ".json"; - - if (!Files.exists(Paths.get(path))) { - System.out.println("File not found: " + path); - continue; + for (Post post : posts) { + String content = post.getContent(); + if (content != null && content.trim().startsWith("{") && content.contains("\"blocks\"")) { + System.out.println("Migrating post: " + post.getTitle()); + String html = convertEditorJsToHtml(content, mapper); + post.setContent(html); + postRepository.save(post); + count++; } - - String json = new String(Files.readAllBytes(Paths.get(path))); - - Optional opt = postRepository.findBySlug(slug); - Post post; - if (opt.isPresent()) { - post = opt.get(); - System.out.println("Updating post: " + post.getTitle()); - } else { - System.out.println("Creating new post: " + title); - post = new Post(); - post.setSlug(slug); - post.setTitle(title); - post.setStatus(PageStatus.PUBLISHED); - post.setCreatedDate(Instant.now()); - post.setLastModifiedDate(Instant.now()); - post.setCreatedBy("admin"); - post.setLastModifiedBy("admin"); - post.setExcerpt("Khóa học " + title + " tại Bệnh viện Đa khoa Quốc tế S.I.S Cần Thơ."); - post.setEventTime(Instant.now().plus(30 + i * 10, ChronoUnit.DAYS)); // dummy start date - } - - post.setContent(json); - postRepository.save(post); } - System.out.println("=== SUCCESSFULLY MIGRATED 4 COURSES ==="); + System.out.println("=== SUCCESSFULLY MIGRATED " + count + " POSTS TO HTML ==="); + } + + private String convertEditorJsToHtml(String json, ObjectMapper mapper) { + try { + JsonNode root = mapper.readTree(json); + JsonNode blocks = root.get("blocks"); + if (blocks == null || !blocks.isArray()) return json; + + StringBuilder html = new StringBuilder(); + + for (JsonNode block : blocks) { + String type = block.get("type").asText(); + JsonNode data = block.get("data"); + + switch(type) { + case "header": + int level = data.has("level") ? data.get("level").asInt() : 2; + String text = data.has("text") ? data.get("text").asText() : ""; + html.append("").append(text).append("\n"); + break; + case "paragraph": + String ptext = data.has("text") ? data.get("text").asText() : ""; + html.append("

").append(ptext).append("

\n"); + break; + case "image": + String url = data.has("file") && data.get("file").has("url") ? data.get("file").get("url").asText() : + (data.has("url") ? data.get("url").asText() : ""); + String caption = data.has("caption") ? data.get("caption").asText() : ""; + html.append("
").append(caption).append("
").append(caption).append("
\n"); + break; + case "list": + String style = data.has("style") ? data.get("style").asText() : "unordered"; + String tag = style.equals("ordered") ? "ol" : "ul"; + html.append("<").append(tag).append(">\n"); + JsonNode items = data.get("items"); + if (items != null && items.isArray()) { + for (JsonNode item : items) { + html.append("
  • ").append(item.asText()).append("
  • \n"); + } + } + html.append("\n"); + break; + case "quote": + String qtext = data.has("text") ? data.get("text").asText() : ""; + String qcaption = data.has("caption") ? data.get("caption").asText() : ""; + html.append("
    ").append(qtext).append(" ").append(qcaption).append("
    \n"); + break; + case "table": + html.append("
    \n"); + JsonNode content = data.get("content"); + boolean withHeadings = data.has("withHeadings") && data.get("withHeadings").asBoolean(); + if (content != null && content.isArray()) { + for (int i = 0; i < content.size(); i++) { + JsonNode row = content.get(i); + html.append(""); + if (row.isArray()) { + for (JsonNode cell : row) { + String cellTag = (withHeadings && i == 0) ? "th" : "td"; + html.append("<").append(cellTag).append(">").append(cell.asText()).append(""); + } + } + html.append("\n"); + } + } + html.append("
    \n"); + break; + case "raw": + String rtext = data.has("html") ? data.get("html").asText() : ""; + html.append(rtext).append("\n"); + break; + case "tabStart": + String ttitle = data.has("title") ? data.get("title").asText() : "Tab"; + // Use a special class so frontend can parse it back into tabs if needed + html.append("

    ").append(ttitle).append("

    \n"); + break; + case "tabEnd": + html.append("
    \n"); + break; + default: + break; + } + } + return html.toString(); + } catch (Exception e) { + e.printStackTrace(); + return json; // Fallback + } } } diff --git a/sisvietnamvn_main/src/main/resources/static/css/custom.css b/sisvietnamvn_main/src/main/resources/static/css/custom.css index 6e955944..32669ba0 100644 --- a/sisvietnamvn_main/src/main/resources/static/css/custom.css +++ b/sisvietnamvn_main/src/main/resources/static/css/custom.css @@ -34,6 +34,8 @@ --spacing-md: 20px; --radius-md: 4px; --radius-lg: 8px; + + --spacing: 0.25rem; } /* ========================================================================== @@ -1083,7 +1085,6 @@ i, .btn-outline-primary { display: flex; flex-direction: column; justify-content: center; - margin-bottom: 2rem; width: 100%; } @@ -1095,6 +1096,7 @@ i, .btn-outline-primary { gap: 4px; /* gap-x-1 */ width: 100%; max-width: 860px; + margin-bottom:calc(var(--spacing) * 8); } @media (max-width: 768px) { @@ -1125,8 +1127,88 @@ i, .btn-outline-primary { background-color: transparent; } -.custom-tab-btn.active { +/* .custom-tab-btn.active { background-color: white !important; color: var(--color-old-brick) !important; /* text-primary-600 */ box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} */ + +@media (min-width: 1280px) { + .xl\:mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } } + +@media (min-width: 768px) { + .md\:mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } +} + +.mb-4 { + margin-bottom: calc(var(--spacing) * 4); +} +/* Editor.js Table Styling */ +figure.table { + width: 100%; + overflow-x: auto; + margin: 2rem 0; +} + +figure.table table { + width: 100%; + border-collapse: collapse; + font-size: 0.95rem; + box-shadow: 0 2px 15px rgba(0, 0, 0, 0.05); + background-color: #ffffff; + border: 1px solid #e0e0e0; +} + +figure.table table th, +figure.table table td { + padding: 12px 15px; + border: 1px solid #e0e0e0; + vertical-align: middle; +} + +/* Biến dòng đầu tiên thành Header luôn cho đẹp nếu người dùng quên bật Header trong Editor.js */ +figure.table table tr:first-child td, +figure.table table th { + background-color: var(--color-old-brick, #881c1c) !important; + color: #ffffff !important; + font-weight: 700; + text-align: center; +} + +figure.table table tr { + border-bottom: 1px solid #e0e0e0; +} + +figure.table table tr:nth-of-type(even) { + background-color: #fcfcfc; +} + +figure.table table tr:hover { + background-color: #f5f5f5; +} + +.training-layout table tr:first-child td, +.training-layout table th { + background-color: var(--color-old-brick, #881c1c) !important; + color: #ffffff !important; + font-weight: 700; + text-align: center; +} + +.training-layout table td, +.training-layout table th { + border: 1px solid #dee2e6; + padding: 8px 12px; +} + +.training-sidebar { + a { + border: white 1px solid; + } +} + diff --git a/sisvietnamvn_main/src/main/resources/templates/dao-tao-detail.html b/sisvietnamvn_main/src/main/resources/templates/dao-tao-detail.html index 7223111c..0ba193ec 100644 --- a/sisvietnamvn_main/src/main/resources/templates/dao-tao-detail.html +++ b/sisvietnamvn_main/src/main/resources/templates/dao-tao-detail.html @@ -73,7 +73,6 @@ .tabs-container { display: flex; width: 100%; - max-width: 500px; border: 1px solid var(--color-primary-600, #a82024); border-radius: 0.5rem; overflow: hidden; @@ -93,7 +92,7 @@ } .dao-tao-tab-btn.active { - background-color: var(--color-primary-600, #a82024); + background-color: var(--color-old-brick); color: white; box-shadow: none; } @@ -129,7 +128,6 @@ .prose-blog table td, .prose-blog table th { border: 1px solid #ddd; - padding: 6px 24px; vertical-align: top; } @@ -142,7 +140,7 @@
    -
    +

    Tiêu đề Khóa học

    @@ -157,48 +155,12 @@
    -
    -
    -
    -
    - - - - - - -
    -
    -

    Thời gian

    -

    27/07/2026 - 27/01/2027

    -
    -
    -
    -
    - - - - -
    -
    -

    Địa điểm

    -

    Giảng đường 3A, lầu 3, khu A, Bệnh viện Đại học Y Dược Thành phố Hồ Chí Minh (215 Hồng Bàng, Phường Chợ Lớn, Thành phố Hồ Chí Minh)

    -
    -
    -
    -
    - - - - - -
    -
    -

    Học phí

    -

    38.000.000 VNĐ

    -
    -
    - Đăng ký +
    + +
    +
    +
    +
    @@ -240,226 +202,85 @@
    - - +
    + + - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/sisvietnamvn_main/src/main/resources/templates/posts/standard.html b/sisvietnamvn_main/src/main/resources/templates/posts/standard.html index b26b370a..bf8186b4 100644 --- a/sisvietnamvn_main/src/main/resources/templates/posts/standard.html +++ b/sisvietnamvn_main/src/main/resources/templates/posts/standard.html @@ -167,175 +167,83 @@ - - +