CHANGELOG - Tân Doanh Theme
Tất cả thay đổi đáng chú ý của theme được ghi tại đây. Quy ước: mỗi ngày làm việc gộp chung một phiên bản [MAJOR.MINOR.PATCH], các chỉnh sửa nhỏ gom vào cùng entry trong ngày.
[1.9.54] - 2026-10-07
Changed · Ảnh hero mobile nhẹ hơn (trang chủ)
- Đăng ký 2 size riêng
td-hero-m-640vàtd-hero-m-768(tỉ lệ 5:4, không crop) tronginc/hero-banner-art.php, CHỈ sinh cho ảnh có têntd-hero-mobile-*(ảnh khác không đẻ thêm file). Trước đó máy 412px DPR 1,75 (Moto G Power, Lighthouse mobile) cần khoảng 721px nên rơi vào bản 960w (44 KB webp); nay chọn 768w (khoảng 31 KB).srcsetcủa<source>và preload LCP lấy chung từ metadata nên tự khớp, không tải đôi. - 4 ảnh hero mobile (ID 3000915-3000918) sinh thêm bản 640 và 768 bằng
wp media regenerate --only-missing; webp do Converter for Media tạo (chất lượng mặc định của plugin).
[1.9.53] - 2026-10-06
Added · Ảnh banner riêng cho điện thoại (hero trang chủ)
- Block
tandoanh/hero-banner: mỗi slide có thêm ảnh điện thoại (mobileImageUrl,mobileImageId,mobileImageWidth,mobileImageHeight). Từ <= 600px trình duyệt tải ảnh này qua<picture><source media="(max-width: 600px)">thay cho ảnh rộng 1920x700 (trước đó bị cắt hai bên, mất chữ và bảng so sánh ở banner 3-4). Slide không có ảnh điện thoại giữ hành vi cũ. Trình soạn thảo có ô "Ảnh riêng cho điện thoại" cho từng slide (chọn, đổi, bỏ). - Khung mobile theo tỉ lệ ảnh (5:4,
--td-m-ar) cówidth/heighttrên<source>vàaspect-ratioCSS nên không dịch bố cục (CLS 0). Slide 1 không lazy,fetchpriority="high"; slide 2+ nạp trễ như cũ (data-td-srcsetbung trong theme.js). - Preload ảnh LCP theo độ rộng (
inc/perf.php): <= 600px preload ảnh điện thoại, > 600px preload ảnh rộng, không tải đôi. Hàm dùng chung ởinc/hero-banner-art.php. - 4 ảnh điện thoại (1080x864) dựng lại bố cục từ 4 banner gốc, nạp vào Media Library (ID 3000915-3000918), gán vào post_content trang chủ.
Changed · Sửa theo review mã vòng 3 trang chủ
- Tên sản phẩm trên thẻ trang chủ tối đa 3 dòng (trước 2 dòng cắt
...ở 22/24 thẻ mobile và 37/55 thẻ desktop; sau: 16 và 4), khoá chiều cao để giá và nút vẫn thẳng hàng. - Build PC trang chủ: tên linh kiện tối đa 2 dòng thay vì 1 dòng cắt
.... - Ô tìm kiếm trên đầu trang: chữ gợi ý (placeholder) dùng màu chữ phụ của theme, không nghiêng, đạt tương phản AA (plugin tandoanh-code ép #999 nghiêng bằng
!importantnên theme ghi đè có chủ đích).
[1.9.50] - 2026-10-06
Fixed · Trang chủ sau review chéo 68 (HR-01..HR-14)
- Đánh giá khách hàng (HR-01/02): block
tandoanh/reviewsloại MỌI đánh giá do AI sinh (metaby_ai/by_auto= 1, kể cả đánh giá AI sinh riêng ở staging) khỏi cả phần trích dẫn lẫn điểm/số đếm. Điểm + số đánh giá tính live từ đánh giá không-AI đã duyệt có chấm sao (trên staging: 155 đánh giá, 4,8/5). Trích dẫn: 5 sao, 70-260 ký tự, mới nhất, không còn điều kiệnverified. Nhãn "Đã mua:" chỉ hiện khi email hoặc tài khoản của đánh giá khớp đơn hoàn thành có đúng sản phẩm đó; còn lại ghi "Đánh giá cho:". Khoá cache transient có version theo bản theme. - Đồng bộ đánh giá: mang cờ AI của bản chính thức sang bản thử (field thứ 9
by_ai, gắn metaby_ai/by_autocho bản mirror, trước đây mất meta); có chế độ chỉ gắn cờ, không thêm hoặc xoá đánh giá. - Newsletter (HR-04): thêm 1 dòng đồng ý dưới form "Bằng việc đăng ký, bạn đồng ý nhận email khuyến mãi từ Tân Doanh và Chính sách bảo mật" (link trang ID 8780), không checkbox bắt buộc.
- HR-05: bỏ padding-bottom 60px/36px của
main.td-home(dải trống giữa newsletter và chân trang). - Build PC trang chủ (HR-06): hàng preset dời lên đầu cả khối (trải 2 cột), 3 chỉ số dời xuống cột phải dưới nút => 2 cột cao gần bằng nhau, hết khoảng trống ~330px. Chỉ trang chủ.
- Hero (HR-07): bỏ giới hạn cao 560px (cắt hàng cuối bảng Windows ở slide 4 và đỉnh tháp ở slide 1 tại 1920); trần 700px = cỡ gốc ảnh 1920x700.
- Vùng chạm / tương phản (HR-09/10/14): link liên hệ chân trang mobile hàng cao 40px; khe 4px giữa các chấm slider mobile; dấu "·" thanh trên cùng aria-hidden + tương phản >= 4,5:1.
- Thẻ SP (HR-12): dòng "Góp ...đ /tháng" luôn 1 dòng (nowrap), không rớt chữ ở mobile.
- Tên sản phẩm (HR-11):
inc/display-title.phpđổi dấu gạch dài thành "-" ở lớp hiển thị (the_title của sản phẩm, tên SP WooCommerce), chỉ frontend; bỏ qua admin, REST, WP-CLI, cron; không sửa DB.
[1.9.49] - 2026-10-06
Changed · 4 trang chính sách khớp tandoanh.vn (A15)
templates/page-chinh-sach-van-chuyen.html: bỏ câu mô tả ô liên hệ ("...đóng gói an toàn cho Quý khách"), giữ tiêu đề + thẻ hotline/email/địa chỉ.templates/page-chinh-sach-bao-hanh.html: bỏ câu "Vui lòng gọi trước khi gửi hàng để được hướng dẫn chi tiết" trong CTA, giữ địa chỉ + hotline + email.- Mục lục các trang chính sách: block chuẩn (group + paragraph + list, className
tdp-policy__toc*, không style inline), CSS thêm cuốipolicy.css,page-chinh-sach-van-chuyen.css,page-chinh-sach-bao-hanh.css(chip, token màu theme, dark tự đúng). - Nội dung 4 trang (post_content) viết lại theo prod: bỏ hero facts và câu không có trên prod. Mở trong trình soạn thảo: 0 block không hợp lệ.
[1.9.48] - 2026-10-06
Changed · Thiết kế lại trang chủ (audit D-10..D-18) + BP-15
- Tiêu đề section 1 kiểu duy nhất: thanh vàng dọc + H2 sans + link chữ "Xem tất cả"; bỏ nhãn [ngoặc] mono và ô icon; đường kẻ khớp container (trước kéo ra 24px mỗi bên). Chỉ còn 1 eyebrow trên trang (Build PC).
- Khu vực nổi bật (D-10): 8 thẻ neon 8 màu thành thẻ than + 1 màu nhấn vàng (ảnh nền SVG giữ nguyên, lọc về đơn sắc vàng), chữ tên 22px, mô tả 13px, nút là chip mũi tên tròn 36px (chữ "Khám phá ngay" còn cho trình đọc màn hình), hết rớt 3 dòng / chữ 7,5px. White Zone giữ thẻ sáng ấm.
- Danh mục nổi bật (D-14): lưới 4 cột từ 1024, 2 cột dưới đó, thẻ ngang (icon vàng phẳng + tên + số SP), bỏ slider/mũi tên. Số sản phẩm đếm LIVE theo link (khớp 8/8 với số ở đầu trang danh mục; số gõ tay cũ lệch, VGA 771 so với 734).
registry/cats/render.php. - Đánh giá khách hàng (D-11): block
tandoanh/reviewslấy đánh giá THẬT từ WooCommerce (5 sao, đơn đã xác minh, mỗi khách 1 lần, tên rút gọn, ghi sản phẩm đã mua); tiêu đề điểm trung bình và số đánh giá tính live (4,8/5 từ 186). Gỡ số liệu và lời chứng thực tự gõ ("4.9/5 từ hơn 12.000 khách", 4 khách không nguồn). Thuộc tínhmanualgiữ đường nhập tay có nguồn. Mobile 1 cột, trích dẫn tối đa 4 dòng. - Newsletter: bỏ câu "Hơn 15.000 khách đã đăng ký" (không có nguồn); form trước đây không lưu gì, nay lưu email vào
wp_td_promo_subscribers(sourcehome) qua RESTtandoanh/v1/subscribe(honeypot, giới hạn 5 lần/10 phút/IP, phản hồi giống nhau cho email mới và đã có). - Hero: mobile cao 208px (trước ~142px) cắt theo điểm nhấn từng slide; desktop 1920 giới hạn 560px (trước 702px); chấm slider vùng chạm 40px ở mobile, chấm có viền để thấy trên ảnh sáng. Dải chữ chạy (ticker) KHÔNG đổi (chốt A12). Khoảng trắng 57px giữa ticker và dải lợi ích đã bỏ.
- TOP bán chạy: giá 0 hiện "Liên hệ" (trước "0đ"), link tiêu đề thành chevron 40px ở mobile; tăng
TD_PRICE_FMT_VERlên 3 để cache cũ tự bỏ. - Build PC trên trang chủ (D-18): eyebrow/nhãn bỏ ngoặc và "//", giá dùng font hiển thị thay mono, chữ phụ >= 12px, nút cuối thẳng hàng đáy cột. Cache
bbfull_*đã UNLINK chọn lọc. - BP-15: nhãn Tài khoản/Giỏ hàng 12px, badge giỏ 12px, chip thanh toán footer 12px, dòng trả góp và nhãn giảm giá thẻ SP 12px; vùng chạm mobile 40px cho nút header (pseudo-element), mạng xã hội footer 40px, link chính sách footer cao 40px.
- File mới
assets/css/home-redesign.css(chỉ trang chủ, nạp sau system.css, không có bản purged);system.cssthêm khối 1.9.48.
[1.9.47] - 2026-10-06
Added · Lớp tương thích shortcode Flatsome
inc/flatsome-compat.php: bài/SP/trang cũ từ theme Flatsome không còn hiện shortcode thô. Đăng ký (chỉ khi chưa tồn tại)[row][col][row_inner][col_inner][section][ux_banner][text_box][ux_text][ux_image][button][gap][divider][title][ux_html][ux_slider][ux_products][tabgroup]/[tab][ux_video][featured_box][message_box][ux_price_table][bullet_item][blog_posts][block id=](CPTblockskhông public, chống lặp).[lightbox]và[page_header]bỏ nội dung.- Tag Flatsome không hỗ trợ (
ux_*,scroll_to,follow...) được gỡ thẻ, giữ nội dung. Không đụng shortcode plugin khác. Lưới 12 cột responsive theospan/span__md/span__sm, ẩn/hiện theovisibility, CSS inline 1 lần chỉ ở trang có shortcode (dark/light theo token). - Dọn
<p>/<br>mồ côi do wpautop quanh khối; chuẩn hoá ngoặc cong trong thẻ Flatsome.
[1.9.46] - 2026-10-06
Changed · Sidebar: nhóm "Danh mục" dạng danh sách điều hướng
- Danh mục con trực tiếp hiện thành danh sách dọc (không còn chip giống nhóm lọc): mỗi dòng là 1 link full rộng cao ≥38px, tên đầy đủ bên trái (dài thì xuống dòng), bên phải badge số SP xám nhạt bo tròn + chevron SVG; kẻ mảnh giữa dòng; hover nền vàng rất nhạt + chữ đậm hơn + chevron dịch 3px; focus-visible rõ. Giữ khung 250px cuộn trong nhóm, icon + tiêu đề hoa; dark theo token; sheet lọc mobile cùng dạng. Không thêm dòng "Tất cả ..." (trùng breadcrumb, là link tự trỏ về trang đang xem). Các nhóm lọc giữ chip.
[1.9.45] - 2026-10-06
Fixed · PDP theo kiểm lại 62
- Breadcrumb PDP ở 390: thuộc tính
hiddenbị.td-bc-i {display:inline-flex}đè nên cấp giữa không ẩn; thêm[hidden]{display:none!important}, JS rút cấp giữa cả khi mục cuối bị bóp dưới 140px, nav không cuộn ngang. - H1: dấu " - " / " | " chỉ dính 1 từ ngay sau (nbsp sau dấu), bỏ U+2060 và
text-wrap: pretty; U+2011 chỉ cho từ ghép ngắn (Type-C), dòng đầu đầy lại. - 720-1279px: thẻ Cam kết + link chính sách xuống dưới gallery (cột trái). ≥1280: dư chiều cao chia 1:2 cho Cam kết : Tư vấn; footer chừa chỗ để FAB không che huy hiệu DMCA.
[1.9.44] - 2026-10-06
Fixed · review chéo 58 (toàn site)
- GR-02: thêm phiên bản định dạng giá
td_price_fmt_ver()/TD_PRICE_FMT_VER(inc/woo/price-format.php) vào khoá cache HTML có giá: grouptd_blocks(topcol_*,psec_*,bbfull_*), transienttd_topcol_*,tandoanh_toprow_*, cache section trang chủ. Đổi định dạng giá chỉ cần tăng số này, cache cũ tự bỏ. Trang chủ hết giá "2,290,000₫". - GR-07: bỏ redirect 302
/page/N/vượt số trang về trang 1; trả 404 như production và hp (inc/woo/woocommerce.php). - GR-03/04: nút Sắp xếp mobile gọn 1 dòng (nút Bộ lọc không còn giành chỗ, nhãn ngắn trùng pill, ≤340px chỉ còn giá trị); mục đang chọn trong sheet Sắp xếp dùng chữ màu chính + nền vàng nhạt + vạch trái + dấu tích (đạt AA, trước 1,68:1).
- GR-09: hệ nút về thang 40/48 (
base.css, mục "Thang chiều cao nút"): nút Gửi bình luận (hết xanh #0046be, vàng thương hiệu 40px bo 8px), giỏ trống 48px, submit CF7 48px, ô + nút Đăng ký 48px, Build PC trang chủ (nút 48, pill 40), "Xem thêm" 40px, nút Bộ lọc/Sắp xếp mobile 48px. Chưa động: nút PDP (Gọi ngay, tab, Build PC PDP, Xem thêm nội dung), icon header mobile 38/34 (cố ý để 7 icon vừa 360px). - GR-08: FAB liên hệ lùi ra khi cuộn xuống (<1200px), hiện lại khi cuộn lên; cột nội dung (lưới + phân trang) chừa đáy 72px (không đụng transform inline).
- GR-05: trang tìm kiếm có breadcrumb "Trang chủ > Kết quả tìm kiếm cho ..." dùng component chung (shortcode
[td_search_crumb]trongtemplates/search.html, nhịp 16/16; thêm lề ngang--td-guttercho.td-search-pageở ≤1344px, trước đó nội dung sát mép màn hình). - Dữ liệu: trang Chính sách vận chuyển (ID 8772) khách lẻ nội thành "8h" thành "24h", ngoại thành "24h" thành "24h-48h" theo bản chính thức.
[1.9.43] - 2026-10-06
Fixed
- PDP ≥768px: bỏ
padding-inlinelặp của.pdp-container(main.td-pdp đã có), breadcrumb và nội dung thẳng mép container như trang danh mục (trước lệch 23px mỗi bên ở 768).
[1.9.42] - 2026-10-06
Fixed · PDP theo review chéo 60
- PF-01:
.desc-layout≤900pxalign-items:stretch+min-width:0(Canon PIXMA G1010 hết tràn ngang 56px ở 390). PF-02: dark mode ép nền inline trắng trong mô tả ngắn/dài về trong suốt (~40 SP), không sửa DB. - PF-03: dư chiều cao chia cho cả 2 thẻ cột phải (Cam kết + Tư vấn, mỗi thẻ space-between). PF-04: H1 dùng U+2060 sau " -" / " |" và U+2011 cho gạch trong từ, chỉ lớp hiển thị (ưu tiên không ngắt xấu hơn mốc 90%).
- PF-05: breadcrumb không cuộn ngang; cấp giữa rút thành "…" khi tràn (giữ Trang chủ + cấp cha gần nhất + mục cuối), mục cuối ellipsis thật (
.td-bc-t). Component chung (system.css + theme.js), áp cả danh mục/shop. - PF-06: FAB chat PDP 1280-1599px dời bottom/right (không đụng transform). PF-07: nút Chỉ đường min-height 44px. Build PC nhẹ lại (nền vàng rất nhạt, viền vàng liền 1px, dark nền surface). Sticky CTA bật cho tablet ≤1279px. Gallery 720-1279px sticky top 84. Sàn collapse mô tả dài 320px. Ghi chú bản quyền (Phần mềm) ra ngoài điều kiện có mô tả ngắn (PF-12). Zalo giữ 0783666668 (khớp prod tandoanh.vn).
[1.9.41] - 2026-10-06
Changed · PDP: Sản phẩm tương tự ưu tiên còn hàng, spacing đều, nút Chỉ đường, mô tả dài theo khối vừa xem
inc/woo/woocommerce.php: "Sản phẩm tương tự" sắp theo nhóm ổn định (1 = còn hàng + giá > 0, 2 = đặt trước có giá, 3 = hết hàng/ngừng KD/giá 0), pool 25 ứng viên rồi cắt 5; tắt shuffle +order=asc(WC mặc định đảo ngược). 1 truy vấn meta cho cả pool (~10-25 ms). Upsell/cross-sell không có trên PDP theme nên không áp dụng.content-single-product.php,single-product.css: thẻ khối mua và thẻ Tư vấn/showroom ≥1280px dùng flex +space-between, MỌI phần là con trực tiếp, khoảng giữa các phần bằng nhau (đo CPU AMD: 14px mọi khoảng; thẻ tư vấn 8px); nhóm mô tả ngắn + nút Xem thêm là 1 phần (.pdp-sd-group); địa chỉ và giờ là 2 phần riêng; nút "Chỉ đường tới showroom" full bề rộng (44px, viền vàng); 3 ô liên hệ icon khung 40x40 bo 10px đồng bộ; bỏ kẻ dưới mục chính sách cuối; sửa dấu}thừa làm hỏng CSS phía sau.- Mô tả dài: thu gọn theo chiều cao khối "Sản phẩm vừa xem" khi 2 cột (đáy nút Xem thêm lệch ≤ 8px với 5 SP; sàn 480px khi ít/không có), cập nhật khi resize/khối vừa xem đổi; Thu gọn cuộn về đầu tab.
[1.9.40] - 2026-10-06
Changed · PDP: tư vấn/showroom ở cột phải, mô tả ngắn lên trên nút mua, nút Build PC, sửa lỗi review
- Cột phải: Cam kết (lọc theo nguồn thật: "1 đổi 1" ẩn với CPU/Máy in/Phòng họp thay bằng "Đổi trả theo chính sách" qua filter
tandoanh_pdp_no_exchange_cats; "Cam kết chính hãng" chỉ khi SP có thương hiệu như badge "Chính hãng"), 4 link chính sách, khối "Tư vấn và showroom" (3 ô Zalo / Messenger / Gọi ngay dùng logo thậtassets/img/contact/*, địa chỉ + giờ nbsp + "Chỉ đường" có icon). Dưới 1280px khối này nằm ngay sau khối mua. - Cột giữa: mô tả ngắn nằm dưới giá, trên hàng nút (giá > mô tả > nút cách đều 16px); nút "Build PC với linh kiện này" (nền tối, viền vàng nét đứt, chip icon, dòng phụ) full bề rộng khối mua; "Cam kết bản quyền" chỉ hiện ở danh mục Phần mềm; H1 22px (mobile 19px)
text-wrap: pretty, gạch " - " / " | " dính chữ bằng nbsp (chỉ lớp hiển thị). td_trim_rich_whitespace()(inc/woo/pdp.php, có kiểm thử 9/9): cắt đoạn rỗng/nbsp/br ở đầu-cuối mô tả ngắn, gộp đoạn rỗng liên tiếp ở giữa, mô tả dài chỉ cắt đầu/cuối; không sửa DB.- Hook server
wp_loaded15 mở rộng cho cả "Thêm vào giỏ" thường: biến thể bấm sớm khi JS WC chưa nạp (variation_id=0) tự khớp theoattribute_*, không khớp thì thông báo thân thiện + về PDP (PR-01). - Sticky CTA mobile hiện khi nút mua chưa nằm TRỌN trong màn (threshold 1). "Sản phẩm vừa xem": hiện tối đa 5 (lưu 6), giá chuẩn "1.390.000đ" kể cả dữ liệu cũ trong localStorage.
- Hàng đầu PDP >=1280px stretch: gallery | khối mua | cột phải có đáy thẳng hàng (đo 1280/1440/1920: lệch 0px, cả SP mô tả dài collapse 360 và biến thể); thẻ tư vấn giãn tới đáy, "Chỉ đường"/Build PC bám đáy thẻ; "Sản phẩm vừa xem" nằm ngoài hàng này. Dưới 1280/mobile xếp tự nhiên.
- CSS: bảng trong mô tả cuộn ngang (hết tràn 12px ở 390), viền thẻ cột phải ~1.5:1 theo token, brand tag/SKU 12px, gỡ rule breadcrumb cũ (đã thuộc system.css).
[1.9.39] - 2026-10-06
Changed · PDP: cột phải gọn, gom thông tin vào cột giữa
woocommerce/content-single-product.php,single-product.css: cột phải chỉ còn "Cam kết của Tân Doanh" (4 dòng ngắn) + 4 link chính sách (đổi trả, bảo hành, vận chuyển, kiểm hàng); cao 354px (trước 1237px) ở 1280/1440/1920. Showroom (địa chỉ + giờ nhóm Kinh doanh từtd_biz()+ link "Chỉ đường" Google Maps) thành 1 dòng nhỏ dưới hàng "Cần tư vấn nhanh?"; "Build PC với linh kiện này" thành link gọn dưới dòng showroom (chỉ SP linh kiện); "Cam kết bản quyền" thành ghi chú 13px dưới danh sách thông số.single-product.css: gỡ rule breadcrumb phẳng cũ (đã bịsystem.cssđè bằng !important); khoảng cách breadcrumb 16/16px không đổi ở 390/768/1440.
[1.9.38] - 2026-10-06
Changed · PDP: mô tả ngắn thu gọn, hàng nút thẳng mép, cột hẹp thứ 3
- Mô tả ngắn (
woocommerce/content-single-product.php,single-product.css): cao tối đa 360px bằng CSS ngay từ đầu (không CLS); JS chỉ thêm.is-fitskhi nội dung ngắn (không có nút) hoặc.is-collapsible(fade về--td-surface+ nút "Xem thêm"/"Thu gọn", chevron SVG xoay,aria-expanded/aria-controls). Áp dụng mọi viewport (trước chỉ desktop, ngưỡng 300/380px), đo lại khi nội dung đổi/resize/font, bấm Thu gọn thì cuộn về đầu khối nếu đã trôi khỏi màn. - Hàng nút mua: bỏ margin-right ~12px còn sót ở nút Thêm vào giỏ, 2 nút chia đều gap 10px, mép trái/phải khớp 0px với thanh Trả góp, đường kẻ và form (đo 390/768/1024/1280/1440/1920; SP đơn giản và biến thể).
- Cột hẹp thứ 3 (
.pdp-sidethành con của grid): >=1280px gallery | khối mua | cột 280px; 720-1279px nằm dưới khối mua; mobile sau khối mua. Không sticky. Nội dung thật: cam kết + link 4 trang chính sách có sẵn (đổi trả, bảo hành, vận chuyển, kiểm hàng,tandoanh_pdp_policy_links()), tư vấn + showroom từtd_biz()kèm link chỉ đường Google Maps theo địa chỉ thật, khối "Build PC với linh kiện này" chỉ với linh kiện thuộc step builder (cầu nối?td_parts=,tandoanh_pdp_build_pc_url()).
[1.9.37] - 2026-10-06
Changed · Thiết kế lại TOÀN SITE + trang shop/danh mục
- D-02 hệ nút:
tokens.cssthêm thang--td-btn-h40 /--td-btn-h-lg48 /--td-btn-h-sm32, bo--td-radius8px (control) và--td-radius-lg12px (card),base.css.td-btnviết lại 3 cấp (primary gold phẳng không gradient/bóng quét, secondary =--ghostviền, text) + danger, đủ hover/focus-visible/active/disabled; nút WooCommerce mặc định cùng thang.assets/css/system.css(mới, nạp cuối) đồng bộ ô tìm, lang/theme/burger (40px từ 768, mobile giữ icon nhỏ), nút Danh mục + Build PC meganav (gold phẳng, bỏ glow/lắc), "Xem tất cả", "Xem thêm", mini-builder trang chủ, giỏ hàng. - D-03: chữ mono chỉ còn cho SKU; nhãn/nút/chip/badge/tab/giá dùng chữ chính, bỏ chữ hoa tracking rộng ở các thành phần dùng chung.
- D-04
inc/woo/price-format.php: giá hiển thị 1 kiểu "1.890.000đ" (filterwc_price_args+woocommerce_currency_symbol, chỉ frontend, AJAX từ frontend và email; không đổi cài đặt WooCommerce, admin/REST giữ nguyên);form-checkout.phpphí gói quà cùng kiểu. - D-01
inc/float-contact.php: cụm 5 nút rời thành 1 nút tròn gold (mọi kích thước) bấm mở danh sách Gọi KD-1, KD-2, Messenger, Zalo, mail; popup xác nhận dùng nút chuẩn; trang có sticky CTA (body.td-scta-on) FAB nằm trên thanh đó; footer chừa đáy. - D-06 toast "đã mua": tên khách chỉ giữ chữ đầu ("N***"), hiện 5 giây, cách nhau >= 60 giây, tối đa 3 lần/phiên, z-index dưới header/sticky/modal, ẩn khi mở popup/lọc, mobile nằm trên sticky CTA (CSS ở system.css).
- D-05: thẻ sản phẩm
woocommerce/content-product.php+woo-card.css: bỏ sao rỗng khi chưa có đánh giá, giá 0 = nút "Gọi tư vấn" (không còn "Mua ngay"), tên khoá 2 dòng để giá/nút thẳng hàng, 1 hệ badge (giảm giá đỏ chữ trắng; nhãn khác gold viền), giá sans tabular màu--td-price, dòng trả góp cho xuống dòng, nút 40px + giỏ 40x40. - D-07: logo giữ tỉ lệ 280:89 (không bị flex ép), mobile cao 34px. D-08: ô ảnh sản phẩm dark nền trung tính
#e8e8eb+filter: brightness(.91)theo token--td-img-bg/--td-img-filter. - D-19/D-22/D-23
archive-product.css+inc/woo/woocommerce.php(bố cục danh mục theo hp, màu vàng TD): hero danh mục ([td_shop_hero]: eyebrow, H1 hiển thị, mô tả thật, 3 cam kết, pill danh mục con 34px, thu gọn ~2 hàng + "Xem thêm (n)" / "Thu gọn"); thanh sắp xếp khung riêng ([td_shop_sortbar]qua hookwoocommerce_before_shop_loop@5: pill Sắp xếp + số đếm, pill 32px vùng chạm >= 40px, AJAX không reload); sidebar lọc nhóm<details>có icon + tiêu đề hoa gạch chân + chip 32px chữ 12px (cỡ chữ lấy từ hp: tiêu đề 14.5px, chip 12px, nhãn sort 12.5px, đếm 12px). Mỗi nhóm lọc cao tối đa 250px cuộn trong nhóm (thanh cuộn mảnh, bóng mờ đáy, tab vào được + focus-visible, áp dụng cả bottom sheet mobile). Sidebar KHÔNG sticky, không cuộn riêng, trôi theo trang. Nhóm "Danh mục" (link chip, chỉ danh mục con trực tiếp, ẩn khi không có; /shop hiện cấp 1) đặt trên "Thương hiệu". - Breadcrumb dùng chung (
system.css): khung viền mảnh, cấp hiện tại là chip vàng nhạt, chevron SVG, mobile cuộn ngang tự cuộn tới cuối, chip cuối ellipsis + title; token--td-bc-gap-top/bottom(16px) đồng bộ khoảng cách trên/dưới giữa trang shop, danh mục và PDP. PDP: Trang chủ > danh mục cha > danh mục chính > chip tên sản phẩm (một schema Rank Math duy nhất). - D-20/D-21: thanh Sắp xếp + Lọc mobile cùng 44px, cùng bo, bỏ chấm gold rỗng; lưới 3 cột từ 700px (2 cột dưới 700, khoảng cách không sát mép).
- D-26 phân trang:
td_pagination_html()dùng chung template + AJAX: nút 40px bo 8px, trang hiện tại gold, Trước/Sau có chevron (vô hiệu ở đầu/cuối), mobile "‹ 1 / n ›"; trang vượt số trang (/page/999) chuyển 302 về trang đầu danh sách. - D-27: thẻ 2 cột mobile padding đều, giá trả góp xuống dòng không sát mép.
- A11y: tên SP trên thẻ ở trang shop/danh mục/AJAX là H2 (dưới H1, không nhảy cấp; trang chủ và trang đơn giữ H3); sort sheet mobile đóng thì
visibility:hidden; Lighthouse accessibility 100. - Gỡ bản
.purged.csscủabase,woo-card,archive-product(nguồn đổi, cần chạy lại purge sau khi duyệt giao diện);enqueue.phpnạpsystem.cssở priority 99.
[1.9.36] - 2026-10-06
Fixed · "Mua ngay" SP simple không tới checkout
inc/woo/pdp.php: nút Mua ngay chỉ gửitandoanh_buy_now=1, cònadd-to-cartnằm trên nút Thêm giỏ nên POST thiếu ID sản phẩm (lỗi có sẵn từ trước đợt redesign PDP). Thêm hiddentandoanh_buy_pidcạnh nút; server (wp_loaded 15) bùadd-to-carttừ đó trước khi WooCommerce xử lý, chuyển tới checkout đúng SP và số lượng. SP biến thể không đổi.
[1.9.35] - 2026-10-06
Fixed · PDP biến thể: "Mua ngay" khi chưa chọn biến thể không còn gửi form lên server
inc/woo/pdp.php: nút Mua ngay/Thêm vào giỏ chưa chọn đủ biến thể ở trạng thái disabled thật (classdisabled+wc-variation-selection-needed,aria-disabled); bấm thì hiện thông báo "Vui lòng chọn phiên bản trước khi mua" ngay tại khối biến thể (không alert), cuộn/focus tới ô chọn, không submit; chọn đủ thì bật lại, reset thì tắt lại. Xử lý cả lúc JS biến thể WC chưa nạp (chặn khi select còn trống; đủ select thì cho gửi). Server (wp_loaded 15): Mua ngay thiếuvariation_idthì tự khớp biến thể từ attribute_*, không khớp được thì quay lại PDP kèm thông báo thân thiện thay vì lỗi WC.woocommerce/content-single-product.php: thanh sticky CTA mobile phản chiếu trạng thái chặn (proxy-click nên cùng thông báo).assets/css/templates/single-product.css: kiểu nút disabled + khung thông báo.
[1.9.34] - 2026-10-06
Changed · Thiết kế lại trang sản phẩm (PDP): bố cục, nút mua, biến thể, hết hàng, responsive
- D-24
assets/css/templates/single-product.css,inc/woo/pdp.php: hàng nút mua SP biến thể là flex 1 hàng (wrapper.woocommerce-variation-add-to-cart+.single_variation_wrap), "Mua ngay" gold phẳng đứng trước, "Thêm vào giỏ" viền; cùng cao 48px, không đè chip biến thể; chip biến thể dựng lại bằng token (tên trái, giá dưới, dấu chọn góc phải không đè chữ, chọn = viền gold đậm); nhãn nút "Thêm vào giỏ" (filterwoocommerce_product_single_add_to_cart_text), "Mua ngay" chữ thường có hoa đầu. Mô tả biến thể (Tình trạng, Bảo hành...) hiện dưới chip. - D-25
woocommerce/content-single-product.php: khối mua chỉ 1 nút chính + 1 nút phụ; "Tính trả góp" thành hàng liên kết có mũi tên; Chat Facebook/Zalo + "Gọi đặt hàng" (3 nút xanh/be) gộp thành 1 hàng link trung tính "Zalo, Messenger, Gọi ngay" (bỏ màu xanh dương). Thông tin nhanh (short desc) chuyển xuống dưới khối mua, bỏ hộp lồng hộp. - D-28
inc/woo/pdp.php: filterwoocommerce_breadcrumb_main_termchọn danh mục chính Rank Math (rank_math_primary_product_cat), không có thì term sâu nhất (WC mặc định chọn term theo ID cha lớn nhất). Kiểm 10 PDP ngẫu nhiên: không hiện tên SP khác. Lưu ý dữ liệu: SP ASUS GT 1030 (ID 105369) chỉ gán danh mục "GTX 1650 4GB" (cần sửa gán danh mục ở production, không sửa dữ liệu ở đây). - D-29/D-30: từ 720px bố cục 2 cột (gallery ~45-50% bên trái, dính khi cuộn; thông tin bên phải); mobile ảnh chính tỉ lệ 4:3, breadcrumb 1 hàng cuộn ngang (phẳng, không khung) tự cuộn tới danh mục sâu nhất; thanh sticky CTA hiện ngay từ màn đầu khi nút mua còn dưới màn hình, giá đầy đủ (bỏ ellipsis, chữ sans tabular), 360-420px nút giỏ thành icon 44px, chừa đáy trang cho thanh.
- D-31: "Sản phẩm vừa xem" ẩn mặc định (
hidden), JS chỉ hiện khi có SP khác trong lịch sử; mô tả/bảng thông số font 14px. - D-32: SP hết hàng: giá lùi màu xám, nhãn "Sản phẩm hết hàng"/"Ngừng kinh doanh" + lời nhắn + nút vàng "Gọi tư vấn: hotline" (không có chức năng báo hàng sẵn, không thêm mới), chữ trạng thái "Hết hàng" ở hàng đánh giá không còn bị ép xanh.
- D-33: bỏ cột phải 300px; 3 thẻ (quyền lợi, bản quyền, tư vấn) gộp thành 1 thẻ "Quyền lợi khách hàng" dưới khối mua (tư vấn kinh doanh/kỹ thuật/email/giờ làm việc từ Thông tin DN, bản quyền thành ghi chú cuối thẻ); thumbnail 1 hàng cuộn ngang.
- D-34: tab chữ thường có hoa đầu, không mono/tracking; "Đánh giá" chỉ hiện số khi > 0.
- Giá PDP: bỏ khung + nhãn "Giá:", số to 28-38px chữ sans tabular, màu
--td-price(fallback--td-danger). - Xoá artifact lỗi thời
assets/css/templates/single-product.purged.css(bản 11/08 thiếu rule mới, theme tự dùng file nguồn khi artifact vắng); cần regenerate nếu muốn bản purge.
[1.9.33] - 2026-10-06
Changed · Cấu hình build sẵn xếp từ rẻ đến đắt
inc/blocks/registry/buildband/render.php: các tab preset ở khối "Tự build dàn PC trong 3 phút" (trang chủ) xếp theo TỔNG GIÁ THỰC TẾ tăng dần (tính sau khi tự thay món hết hàng); preset "Liên hệ báo giá" xuống cuối; tab đầu (mặc định) là preset rẻ nhất. Chỉ đổi thứ tự lúc render, dữ liệu preset không sửa, nút Build PC/Thêm vào giỏ vẫn theo từng preset.
[1.9.32] - 2026-10-06
Changed · Tốc độ mobile 3 landing PC, Hot PC, Kèo Thơm (Lighthouse mobile 82-91 lên 98-100, LCP 3,2-3,6s xuống 1,7-2,4s)
- Gốc: webfont (Inter, JetBrains Mono, Be Vietnam Pro 190KB + font riêng 3 landing PC 195KB) là request ưu tiên cao tải xong TRƯỚC FCP nên bị tính vào đường tới FCP/LCP trên Slow 4G (FCP 3,0s). Chữ vẫn hiện ngay bằng font fallback khớp metrics rồi swap, giao diện cuối không đổi.
inc/late-fonts.php(mới): trangpc-gaming,ai-workstation,creator-studio,hot-pc,keo-thomđổifonts.csssangfonts-fallback.css(chỉ @font-face local) và nạp webfont SAU first-contentful-paint bằng script inline: đọcfonts-web.css+landing-{slug}-fonts.css, chỉ tải subset có ký tự trong trang, tải xong hết rồidocument.fonts.addmột lần (1 lần dựng lại chữ thay vì mỗi font một lần). Dự phòng sau load + 1,5s hoặc 4s,<noscript>giữ link CSS. Chế độ so sánh/rollback: thêm?td_fonts=blockingvào URL (nạp font như cũ, landing nạp lại file font bằng link CSS thường).assets/css/fonts-fallback.css,fonts-web.css(mới, sinh từfonts.css;fonts.cssvẫn là nguồn, đã ghi chú ở đầu file).assets/css/landing-perf.css(mới, chỉ <= 480px):content-visibility:auto+contain-intrinsic-size(chiều cao đo ở 390px) cho các section dưới màn hình đầu, dựng lại chữ khi font về từ ~40ms xuống ~15ms. Bấm link neo hoặc vào bằng #hash thìhtml.td-nocvtắt hẳn (landing-enhance.js) để cuộn đúng vị trí thật.assets/js/landing-enhance.js: bỏ các lần đọc layout đồng bộ lúc nạp (scroll-spy chạy lần đầu sau khung hình, đo khối bọc section thay vì section trong vùng content-visibility, thanh GPU meter chờ 2 khung hình thayoffsetWidth).assets/css/landing-enhance.css: fallback 'Inter Tight Fallback' đổi size-adjust 99,3% thành 95% (đo trong Chrome trên đoạn văn tiếng Việt thật: webfont/Arial 0,947-0,953), thêm fallback riêng cho tiêu đề IN HOA theo từng landing (gaming 94,6%, ai 92,4%, creator 93%). Chiều cao hero khi dùng fallback và khi webfont về khớp nhau ở 360-1350px. CLS pc-gaming mobile 0,077 và desktop 0,117 xuống 0.inc/lcp-banner.php(mới): ảnh banner đầu trangkeo-thom(HTML thô trong post_content) được gắnwp-image-IDđể lõi thêm width/height + srcset, bỏloading="lazy", thêmfetchpriority="high"(CLS 0,112 xuống 0, ảnh mobile tải bản nhỏ thay vì 2560px). Không sửa dữ liệu bài.inc/blocks/registry/hotpc-hero/render.php: ảnh hero Hot PC có srcset/sizes (mobile ~460px thay vì ảnh 1920px),fetchpriority="high".
[1.9.31] - 2026-10-06
Fixed · QA tổng td (A11y light/dark, giỏ hàng, checkout, trang chủ)
- Q-02
inc/woo/pdp.php: "Sản phẩm vừa xem" lưu giá dạng text thuần (bỏ<del>/screen-reader-text, giải mã entity, đổi dấu gạch dài thành "-"); JS bóc thẻ + giải mã bằng DOMParser cho dữ liệu cũ đã lưu trong localStorage (không còn hiện HTML giá thô). - Q-03
inc/blocks/registry/biz-text/render.php(varianth1, token{brand}) +templates/front-page.html: thêm H1 ẩn trực quan (screen-reader-text) cho trang chủ. - Q-04
woocommerce/content-single-product.php: thanh.td-sticky-ctaẩn dùnginert(fallbacktabindex=-1) thay vìaria-hiddenbọc nút focus được. - Q-05:
--td-successlight #1a8f4c đổi #157a3d (4,13 thành 5,4:1; cập nhậttokens.css,theme.json, 5 file critical); tiêu đề giỏ hàng đúng thứ bậc (item h2, khối h3, tên phụ kiện h4, 4 thẻ cam kết h3; CSS theo); checkout: ô Select2 Tỉnh/Phường cóaria-labelledbytới label (checkout.js, MutationObserver), placeholder Select2 dùng--td-text-2và bỏ opacity ô disabled,.showlogin/.showcoupondùng--td-link-hover, chữ đỏ inline trong mô tả cổng thanh toán được override màu bằng CSS (option DB giữ nguyên);inc/a11y.php: meta description cho Giỏ hàng/Thanh toán qua filterrank_math/frontend/description. - Q-06: landing
--ink-3tối #82796b đổi #9a9181 (sửa ở nguồnlanding-clone/*.html, bản sinhassets/css/landing-*.css,landing-enhance.css;scrub_labels()giữ idempotent); trang hướng dẫn trả góp, nhãn/ghi chú ô nổi bật.tdp-tragop__estat--hldùng--td-text-2. - Q-07
layout.css+layout.purged.css: badge số giỏ ở dark dùng chữ tối #14110a trên nền #ff6257 (6,4:1). - Q-09
inc/admin/business-info.php: bỏ dấu gạch dài khỏi tên công ty mặc định (optiontandoanh_business_infovà 3 chỗ "18 - 70", "10 - 30" trong trang hướng dẫn trả góp ID 55836 đã sửa trong DB, có backup); icon "play" của mục Discipline landing creator thành SVG inline (landing-clone,landing-inline,creator-discipline.html). inc/landing.php::tandoanh_land_live_display(): cả 4 màn hình bị ẩn thì bỏ luôn khung.cr-display-monitors(khối hiệu chuẩn chiếm cả hàng, câu dẫn không nhắc "bên dưới").
[1.9.30] - 2026-10-06
Changed · Landing creator: giá màn hình lấy live, hết hàng thì ẩn dòng
- Mục "Màn hình & màu" (
creator-display.html,landing-inline/creator-studio.html,landing-clone/creator-studio.html): mỗi dòng mangdata-td-pid(ID sản phẩm) và token{{td_price:ID}}thay cho giá gõ tay. inc/landing.php: hàmtandoanh_land_live_display()đọc giá hiện hành lúc render; sản phẩm hết hàng, giá 0, đặt trước, ngừng kinh doanh hoặc không còn tồn tại (quy tắc A1) thì ẩn cả dòng. Gọi ở bản inline vàland-section/render.php.
[1.9.29] - 2026-10-06
Changed · Script sinh landing đồng bộ với nội dung hiện tại (chạy lại không ghi đè)
- Kiểm: sinh lại vào bản sao theme (cả từ trạng thái trước 1.9.28) cho kết quả giống hệt file đang chạy.
[1.9.28] - 2026-10-06
Changed · Landing PC: bỏ nhãn gợi "live"/phòng lab, màn hình creator là hàng đang bán
- Hero gaming (
land-section/sections/gaming-hero.html,land-hero/scenes/gaming.html,landing-inline,landing-clone): "LIVE FPS · 4K ULTRA" thành "FPS tham khảo · 4K Ultra"; "TAN DOANH PC LAB · APEX-X9" và "APEX-X9 · LIVE TELEMETRY" thành "Cấu hình tham khảo"; 5 SVGassets/landing-svg/gaming-build-*.svgbỏ chữ "PC LAB". - Creator: "OctaneBench · score" thành "OctaneBench · điểm tham khảo"; mục màn hình (
creator-display.html) thay BenQ/Eizo/Apple bằng 4 màn hình đồ hoạ shop đang bán (ASUS ProArt PA278QEV, PA279CV, PA329CRV, ViewSonic VP2788-5K), tên đầy đủ có link sản phẩm, giá hiện hành. - Ghi chú: EAGLE PSU thực tế là MSI MAG A850GL 850W (ID 75592), không phải FSP Vita 750W.
[1.9.27] - 2026-10-06
Fixed · Trang chủ cache lạnh chậm và cache block preset Build PC
inc/blocks/registry/buildband/render.php: benchmark tự sinh (td_bench_auto_groups, khoảng 290 truy vấn, 1,4s cho 6 preset) có cache object theo dấu dữ liệu bảngwp_td_benchmarks(tandoanh_bp_bench_cached, TTL 12 giờ). TTFB trang chủ cache lạnh 2,5s xuống 1,3s.inc/home-sections.php: khoá cache block buildband gồm thêmTanDoanhBuildPC_Security::cache_epoch()(td_buildpc_version), nên đổi giá/tồn kho qua đường không gọiwoocommerce_update_productcũng làm block tính lại.
[1.9.26] - 2026-10-06
Fixed · Widget preset Build PC (buildband) in giá đúng chuẩn Việt Nam
inc/blocks/registry/buildband/render.php: giá từng linh kiện, dòng "Linh kiện", giảm giá và tổng in4.290.000đ(number_format( $x, 0, ',', '.' )) thay vì4,290,000đ.
[1.9.25] - 2026-10-06
Changed · Landing PC (pc-gaming, ai-workstation, creator-studio): chữ theo chính sách và dữ liệu thật
- Gỡ các câu không có nguồn: "12K+ PCs đã giao", "4.9 · 2.4K reviews", "24/7", "thuê thử / Try Before Buy", "Tân Doanh PC Lab đo trên hệ thống thực", burn-in 48h, "bảo hành toàn bộ linh kiện 36 tháng", "ship HCM trong ngày", đổi mới 1-1 trong 6 tháng, ICC profile / calibration / training / LUT đi kèm mọi máy, "đối tác chính thức Eizo, BenQ, Apple". Thay bằng nội dung khớp trang Chính sách vận chuyển, bảo hành, hàng hóa (giao miễn phí nội thành HCM trong 24h với đơn ráp máy, đổi mới 7 ngày nếu lỗi nhà sản xuất, khách tỉnh thanh toán trước).
- Khối "Quyền lợi" (trước là Ưu đãi): chỉ nêu quyền lợi có trong chính sách, không quà tặng. Mục FPS / AI bench / app bench ghi rõ là số tham khảo, không phải đo tại Tân Doanh; telemetry hero ghi "minh hoạ".
- Hero: thống kê gaming lấy số cấu hình, giá trị chính sách, điểm và số đánh giá thật từ đánh giá sản phẩm WooCommerce (token
{{td_rating}},{{td_review_count}}, transient 6 giờ); hero AI và creator lấy VRAM, RAM, SSD, CPU của cấu hình mạnh nhất (RTX PRO 6000 96GB, 256GB ECC; terminal demo 1 GPU thay cho 4 GPU 192GB). - Token mới trong markup landing:
{{td_hours}},{{td_hours_short}}(giờ làm việc từ Business Info), cùng{{td_phone}},{{td_address}}có sẵn. Hàmtandoanh_land_tokens(),tandoanh_shop_rating()(inc/landing.php),td_biz_token_map(),td_biz_expand_tokens()(inc/admin/business-info.php). - Sinh bằng script dựng landing (chạy lại nhiều lần ra cùng kết quả) và script cập nhật block hero AI trong DB.
- TD-EAGLE đổi RX 9070 XT sang MSI GeForce RTX 5070 12G VENTUS 2X OC (kiểm PSU, socket, tản nhiệt: 0 cảnh báo, 15/15 cấu hình).
Changed · Giờ làm việc dùng chung một nguồn
td_biz_hours_rows(),td_biz_hours_text(); shortcode[td_biz field="hours"](hoặckey="hours",hours_short). Thẻ "Giờ làm việc" trang Liên hệ (contact-cards, trườngsource: hours) và khối CTA trang phần mềm bản quyền (prem-cta, token{{td_hours}}) đọc từ Business Info, khớp footer. Gạch dài trong giờ làm việc đổi thành "-" (mặc định, option, bản dịch /en/).
Fixed
- Bảng giá thu mua (
inc/buyback-pricelist.php): ở lớp hiển thị đổi "GTX 2060/2070/2080" thành "RTX", "Gigabye" thành "Gigabyte", gạch dài thành "-" (nguồn Google Sheet giữ nguyên). - Rank Math: mô tả và tiêu đề 3 landing bỏ claim không có nguồn. Hot PC: khối "Giao và hỗ trợ tận nơi" đổi theo chính sách thật.
[1.9.24] - 2026-10-06
Added · Lõi tính trả góp phía server (inc/installment-calc.php)
tandoanh_installment_calc_card(),tandoanh_installment_calc_finance(),tandoanh_installment_calc()tương đươngcalcCard/calcFinancecủainstallment-core.js(cùng công thức, cùng cách làm tròn đồng và làm tròn lên 1.000đ, cùng tên khoá kết quả);tandoanh_installment_check_card()/_check_finance()kiểm điều kiện đơn vị;tandoanh_installment_resolve( $token, $amount )đọc lựa chọn dạngcard:VIB:6hoặcfin:pk1:12:20, kiểm với cấu hình đang bật rồi tính;tandoanh_installment_compare()bảng so sánh các kỳ hạn. Dùng cho trang in A4 của plugin tandoanh-buildpc 2.8.0. Đã kiểm tương đương JS và PHP (6 ca, mọi khoá khớp).
Added · Widget preset Build PC tự thay món hết hàng (inc/buildband-substitute.php, inc/blocks/registry/buildband/render.php)
- Dữ liệu preset (sync từ production) không bị sửa. Lúc render, món không còn bán (không publish, hết hàng, đặt trước, ngừng kinh doanh, giá 0) được đổi sang món đang bán cùng bước/danh mục (từ danh mục lá lên cha), giá gần nhất (khoảng ±25%, ±50%, rồi không giới hạn; giá gốc 0 thì lấy giá trung vị cùng nhóm), RAM ưu tiên cùng dung lượng và loại RAM laptop/ECC bị loại; món thay phải qua
tandoanh_landing_check_compat()(socket, DDR, tản nhiệt, case) và ước tính công suất nguồn của plugin Build PC. Chỉ khi không tìm được món thay mới hiện "Tạm hết" hoặc "Liên hệ báo giá". - Món được thay có nhãn nhỏ "Đã thay món tương đương (thay cho ...)" (rê chuột hoặc focus bàn phím); tổng, pill, hộp tương thích, nút "Thêm vào giỏ" và "Tuỳ chỉnh cấu hình" (td_parts + td_qty) dùng bộ linh kiện hiệu lực. Kết quả cache transient theo
td_buildpc_version(Redis) nên đổi giá/tồn kho hoặc chạy sync là tính lại. - CSS nhãn và tooltip trong
assets/css/templates/home.cssvàhome.purged.css.
[1.9.23] - 2026-10-05
Fixed · Vá lỗi review module "Tính trả góp" (inc/tragop-admin.php, inc/tragop-data.php, inc/installment.php)
- Import XLSX chặn zip bomb: tối đa 50 mục trong file, kích thước giải nén khai báo của
sharedStrings.xml+sheet1.xmltổng không quá 20MB (kiểm bằngstatName, đọc có giới hạn), bảng không quá 500 dòng; chỉ đọc sheet1 + sharedStrings. Bọclibxml_use_internal_errorsđể file lỗi không in PHP Warning. - Làm sạch tên khi nhập:
sanitize_text_field, bỏ ký tự công thức= + - @đầu tên (chống CSV/formula injection), tối đa 60 ký tự, tối đa 100 đơn vị mới mỗi lần nhập. - Phí 0% hợp lệ ở ô phí kỳ hạn (admin lưu tay và nhập bảng): 0 khác trống/"x" (không hỗ trợ). Hướng dẫn trong admin cập nhật.
- Link hướng dẫn chỉ nhận http/https hoặc đường dẫn nội bộ: lưu qua
esc_url_rawgiới hạn scheme, cấu hình công khai và JS kiểm lại. - Admin: ô tên đơn vị rộng 260px (hết cắt chữ); ghi chú nút "Tính trả góp" chỉ hiện khi giá từ mức tối thiểu thấp nhất của các đơn vị đang bật; thông báo dùng giọng hệ thống trung tính; mobile: ô chọn kỳ hạn và link hướng dẫn cao 44px.
[1.9.22] - 2026-10-05
Changed · Widget preset Build PC trang chủ (inc/blocks/registry/buildband/render.php)
- Gọi plugin
tandoanh-buildpc2.7.0 (TanDoanhBuildPC_Compat::preset_report) khi plugin có sẵn: món hết hàng, đặt trước, ngừng kinh doanh hiện "Tạm hết", món giá 0 hiện "Liên hệ"; có món như vậy thì nhãn pill, dòng "Linh kiện" và "TỔNG CỘNG" hiện "Liên hệ báo giá" thay vì cộng thiếu. - Hộp "Tương thích" kiểm thật (socket CPU và mainboard, loại RAM, công suất nguồn ước tính); cảnh báo dùng khung vàng theo token
--td-brand-strong, không còn chuỗi cố định có tick xanh. Không có plugin thì giữ chuỗi cũ (đã đổi gạch dài thành "-"). - Mở link share của preset thì gia hạn
updated_atcủa share (cron dọn phiên 90 ngày của plugin).
[1.9.21] - 2026-10-05
Added · Module "Tính trả góp" (thẻ tín dụng + công ty tài chính)
- Frontend lazy (
assets/js/installment-core.js,installment-ui.js,assets/css/installment.css): modal (mobile là sheet đáy) với tab "Thẻ tín dụng" (chọn ngân hàng, kỳ hạn hỗ trợ, báo rõ khi dưới/vượt mức, gợi ý đơn vị phí thấp nhất) và tab "Công ty tài chính" (gói vay, trả trước %, kỳ hạn, gợi ý tăng trả trước khi vượt hạn mức vay). Kết quả: góp mỗi tháng, phí/lãi, tổng phải trả, chênh lệch so với trả thẳng, kỳ đầu/kỳ sau, hạn mức thẻ cần có, bảng so sánh các kỳ hạn. Dark/light theo token, a11y (dialog, focus trap, Esc, tab bằng phím mũi tên, vùng kết quả aria-live). - Lõi tính thuần + unit test: thẻ phí = số tiền x % kỳ hạn (+ phí quẹt nếu bật), góp = (số tiền + phí) / kỳ hạn làm tròn lên 1.000đ; công ty tài chính lãi phẳng hoặc dư nợ giảm dần (niên kim).
- API cho trang khác (Build PC...):
window.tdInstallment.open({amount,title}),.mount(el,opts),.setAmount(n),.calc(...),.getLast()(lựa chọn gần nhất, sessionStorage),.planHtml(plan?)(khối "Kế hoạch trả góp" in A4), sự kiệntdinstallment:change. PHP:tandoanh_installment_button(),tandoanh_installment_public_config(),tandoanh_installment_product_eligible(). RESTGET /wp-json/tandoanh/v1/installment-config(cache 5 phút). - Admin Installment (
inc/tragop-admin.php): bật/tắt từng đơn vị, sắp xếp bằng mũi tên, loại (ngân hàng / công ty tài chính), giá trị tối thiểu + tối đa, phí nhập "2,05" hoặc "2.05" (kiểm tra 0 đến 100), công tắc "cộng phí quẹt thẻ" + % quẹt, gói vay công ty tài chính (lãi, trả trước tối thiểu, hạn mức vay, kỳ hạn), cách tính lãi, dòng miễn trừ, link hướng dẫn, ngày cập nhật bảng phí. Nhập bảng phí từ file .xlsx (ZipArchive + SimpleXML), .csv hoặc dán bảng; khớp đơn vị theo tên, có sao lưu và nút hoàn tác 1 bước. - Cấu hình mới trong option
tandoanh_tragop_options(autoload no), đọc quatandoanh_tragop_settings(); option cũ thiếu khoá thì dùng mặc định (không mất dữ liệu).
Changed
- PDP: nút "Tính trả góp" (giá > 0, còn hàng, đủ mức tối thiểu; giá theo biến thể đang chọn) thay khối modal + bảng tính inline cũ (PDP nhẹ hơn khoảng 10KB truyền tải theo Lighthouse; CSS/JS chỉ nạp khi khách bấm hoặc rê chuột vào nút).
- Giá trong modal theo biến thể đang chọn: tra
variation_idtrongdata-product_variations, tự khớp theo thuộc tính khi JS biến thể WooCommerce nạp trễ, kèm sự kiệnfound_variation/reset_data. [td_tragop]nhúng cùng giao diện mới (nạp lười khi cuộn tới).tandoanh_installment_monthly()và bảng phí[td_tragop_table]tôn trọng bật/tắt và giá tối đa từng đơn vị.- Lưu admin không còn
wp_cache_flush()(xoá cả Redis), chỉ xoá cache HTML WPFC.
[1.9.20] - 2026-10-05
Fixed · Cầu nối số lượng Build PC (inc/landing.php)
- Cầu nối
td_parts/td_qtychỉ chạy trên trang/tu-chon-cau-hinh-pc/, chỉ khi cả hai tham số là chuỗi; mọi URL khác không tạo transient. td_parts[]=hoặctd_qty[]=(kiểu mảng): bỏ qua êm, không còn PHP Warning "Array to string conversion" (gỡ khỏi$_GETđể preload plugin cũng không cảnh báo).td_qtychỉ nhận số nguyên 1..16 (âm, 0, chữ, số thập phân bị loại, không cònabsint).- Khoá chia sẻ theo md5 nội dung (cùng cấu hình dùng lại 1 transient), tối đa 30 khoá mới mỗi giờ mỗi IP.
[1.9.19] - 2026-10-05
Fixed · Landing PC vòng 2 (sửa lỗi review chéo đợt 1.9.18)
- Tản nhiệt hợp socket CPU: TD-TRAIN / TD-QUAD / TD-THREAD (Threadripper sTR5) dùng Noctua NH-U14S TR5-SP6 (hãng ghi sTR5/SP6, tương thích Threadripper PRO 7995WX); trước đó gắn Kraken Elite 420 V2 chỉ hỗ trợ LGA1851/1700/1200/115X + AM5/AM4. TD-INFER (Core Ultra 7 265K, LGA1851) đổi ID-Cooling FX360 ARGB (không ghi LGA1851) sang FX360 INF (hãng ghi LGA1851/1700 + AM5/AM4), cùng giá.
- Case chứa được mainboard: TD-TRAIN / TD-STUDIO (mainboard E-ATX TRX50) đổi Corsair 7000D (thuộc tính ATX) sang Thermaltake AX700 (E-ATX/XL-ATX/EEB).
- RAM dual / quad channel: các build từ gaming tầm trung trở lên dùng 2 thanh 16GB DDR5 (tổng giá nhân đủ số lượng, spec ghi "32GB (2x16GB) DDR5-6000"); build Threadripper dùng RAM ECC Registered 32GB: 4 thanh (TRX50, quad channel, 128GB), 8 thanh (WRX90, 8 kênh, 256GB). TD-FOX giữ 1 thanh DDR4.
- Nút Build PC truyền đúng số lượng: link
?td_parts=ID,ID&td_qty=ID:SL(3 clone JS + bảng so sánh + thẻ tóm tắt);inc/landing.phpthêm cầu nốitemplate_redirectưu tiên 3 dựng khoá chia sẻ với số lượng (preload của plugin buildpc luôn nạp số lượng 1). REST/build-pricenhận tối đa 24 ID mỗi cấu hình; transienttd_buildprice4_. - Kiểm tương thích tự động
tandoanh_landing_check_compat()(inc/landing-builds.php): socket CPU-mainboard, DDR, RAM ECC Registered chỉ trên sTR5, tản nhiệt hỗ trợ socket CPU (đọc mô tả SP), case chứa form factor mainboard. Script dựng landing in lỗi/cảnh báo và từ chối sinh markup khi còn lỗi. - Đổi tên build TD-XEON (dùng Threadripper PRO, không phải Xeon) thành TD-THREAD, tier "Flagship Workstation".
- JS thẻ build: khi cấu hình thiếu món (
ok:false) giữ nguyên spec tĩnh, không ghi đè lệch nhãn. - Khối "VGA MSI" (trang MSI) hiện lại: nhánh
source=keywordcủa product-list khớp cả danh mục con (inc/home-sections.php). - Meta description 3 landing PC (gaming, AI, creator) viết lại đúng cấu hình hiện có.
- Tắt
wptexturizetoàn site (inc/content-enhance.php): H1 "Kèo Thơm - Tri Ân Khách Cũ" không còn bị đổi thành gạch ngang dài; tiêu đề block MSI/ASRock đổi dấu gạch dài thành "-".
[1.9.18] - 2026-10-05
Fixed · Landing PC (pc-gaming / ai-workstation / creator-studio): cấu hình dựng từ linh kiện ĐANG BÁN
- Quy tắc A1 (
inc/landing-builds.php, mới): linh kiện chỉ được dùng/hiển thị khi publish + giá > 0 +stock_status = instock(loại hết hàng, ngừng KD, đặt trước). Cấu hình 15 build ởinc/landing-builds-config.php(nguồn duy nhất); 14/15 build đã thay linh kiện giá 0 / hết hàng bằng SP tương đương đang bán (kiểm socket CPU-main, DDR4/DDR5, PSU >= TDP CPU+GPU x 1.5). - REST
/tandoanh/v1/build-price(inc/landing.php): bỏ lỗi âm thầm bỏ qua món giá 0 (làm giá thấp giả, vd TD-DRAGON 46,67tr thay vì ~237tr). Thiếu 1 món đang bán thì trảok:false+ "Liên hệ báo giá" thay vì cộng thiếu. Trả thêmspecs(CPU/GPU/RAM/SSD/PSU sinh từ tên SP thật) + danh sách ID lỗi; transient keytd_buildprice3_. - Spec in trên card, bảng so sánh, thẻ "Build hiện tại"/"Recommended"/"Selected", 4 thẻ Linh kiện, telemetry hero gaming, chữ trên 5 ảnh SVG gaming-build: sinh từ linh kiện thật bằng script dựng landing (chạy lại nhiều lần ra cùng kết quả). Bỏ text cứng sai (ARM Cortex 128GB, RTX 4090 cũ, giá gạch "ưu đãi" cứng, hàng FPS/VR/Capture không có dữ liệu).
- Clone JS (8g): cập nhật giá + spec live từ REST, gán giá cho mọi ô
[data-td-price](bảng so sánh, thẻ tóm tắt). - FAQ: hotline + địa chỉ showroom lấy từ td_biz qua token
{{td_phone}}/{{td_address}}(land-section render.php + inline), bỏ hotline 1900.6868 và địa chỉ cũ; đổi tên build cũ (ORCA/KRAKEN/AMBER/COPPER/BRONZE/RUST/MAHOGANY...) thành tên build thật. - gaming-promo: gỡ đồng hồ đếm ngược giả + "Mega Sale 5.5", thay bằng khối "Quyền lợi khi mua PC tại Tân Doanh"; nút điều kiện trỏ trang chính sách thật; promo AI/creator: link
#thành/lien-he/. - Terminal AI: hostname giả
td-orcathànhdemo. - Dọn CSS rỗng
background-position-x: ;trong markup sinh ra.
Added · Lọc SP đang bán cho block danh sách
tandoanh/product-list+tandoanh/product-sectionthêm attributesellable(+orderby): chỉ giữ SP publish, còn hàng, giá > 0; source động dựng ID theo total_sales giảm dần rồi giá giảm dần; không đủ thì hiện ít ô hơn (không lấp bằng SP khác). Áp cho hot-pc, 4 trang TOP, 5 trang thương hiệu, kèo thơm, phần mềm.- Shortcode
[td_price id=""]: giá live của 1 SP (SP không còn bán thì "Liên hệ"), dùng cho bảng giá cứng trong nội dung trang.
[1.9.17] - 2026-08-29
Added · Sticky CTA bar mobile PDP (đề xuất QA - tăng chốt đơn)
- Thanh mua cố định đáy màn khi khách cuộn qua nút mua chính (mobile <768px). CHỈ hiện khi SP mua được (
is_purchasable && is_in_stock). Nút sticky "Thêm giỏ"/"Mua ngay" proxy-click nút thật (.single_add_to_cart_button/.tandoanh-buynow) → giữ nguyên validate biến thể + buy_now. Giá + thumbnail đồng bộ theo biến thể qua MutationObserver. Hiện/ẩn bằng IntersectionObserver observe NÚT mua (chính xác lúc CTA chính khuất). Khi hiện, dời FAB chat (#td-contact-mdock) lênbottom:88pxđể không đè nút Mua ngay. Build động JS + CSS inline trong template, chỉ SP purchasable. Verify browser mobile (390px): render + FAB clear + proxy OK. - (QA report review: 2.3 dark tab contrast + 2.4 buildpc loading state + floating total + 2.5 Z Fold padding - VERIFY đều ĐÃ CÓ/ĐÃ ỔN sẵn trên TD, không cần sửa. Chỉ Sticky CTA là mới.)
[1.9.16] - 2026-08-27
Fixed · A11y filter UX (Lighthouse audit ui-ux-pro-max) - regression từ 1.9.14
- color-contrast: text phụ toolbar (
.td-shop__toolbar-count,.td-sort-open__val, chip ×,.td-active-clear, empty-statep, sortsheet close) dùng$muted55% → không đạt 4.5:1. Nâng lên 72% (color-mix(--td-text 72%,transparent)) → pass. Shop A11y 97→100. - label-content-name-mismatch: nút
.td-sort-opencóaria-label="Sắp xếp sản phẩm"không chứa text hiển thị động ("Sắp xếp" + giá trị "Mới nhất"). Bỏ aria-label → accessible name lấy từ text hiển thị (đúng chuẩn WCAG label-in-name).
[1.9.15] - 2026-08-24
Added · Gallery PDP đổi theo biến thể (cặp với plugin tandoanh-code 6.8.2 module variation-gallery)
- Refactor JS gallery inline trong
woocommerce/content-single-product.phpđể hỗ trợ ĐỔI gallery theo biến thể khách chọn: táchbindThumbs()(rebind được sau khi dựng lại strip), lưu gallery gốc, và expose 2 hàm global cho plugin gọi:window.tdRenderGallery(images)- dựng lại ảnh chính + strip thumbnail từ mảng[{id,thumb,medium,full,alt}](dựng bằngcreateElement/textContent- an toàn XSS). Nếu SP gốc chỉ 1 ảnh (không có strip) mà biến thể nhiều ảnh → tự tạo[data-td-thumbs](đánh dấudata-td-dynamic).window.tdResetVariationGallery()- khôi phục gallery gốc khi khách bỏ chọn biến thể (gỡ strip động nếu có).- Lightbox nay đọc LẠI
srcstừ DOM mỗi lần mở (thay vì chụp 1 lần lúc load) → đúng khi gallery đã đổi theo biến thể.
- Không đổi hiển thị khi SP không có ảnh gallery-biến-thể (đa số hiện tại) - chỉ kích hoạt khi biến thể có
_ux_additional_variation_images/ảnh đại diện riêng. - Review mã fix 2 finding (M): (a) SP cha KHÔNG có ảnh (placeholder, thiếu
#pdp-main-img) mà biến thể có ảnh →ensureMain()tạo#pdp-main-imgđộng (ẩn placeholder; reset gỡ + trả placeholder); lightbox chuyển sang delegation trên#pdp-main-wrap+ re-resolve main để chạy được với main động. (b) Sang biến thể chỉ 1 ảnh nay CLEAR hẳn strip thumbnail (không chỉ ẩn) để lightbox không đọc nhầm ảnh biến thể trước.
[1.9.14] - 2026-08-23
Perf · Chặn thumbnail rác khi upload - whitelist size theme thật dùng (port HP 1.9.17)
- Thêm filter
intermediate_image_sizes_advanced@999: CHỈ sinh các size ĐÃ ĐĂNG KÝ (get_intermediate_image_sizes()+ 3 size WooCommerce), gỡ1536x1536/2048x2048(WP big-image retina theme không dùng) và MỌI size lạ plugin chèn. Verify: GIỮ thumbnail/medium/medium_large/large/small/td-responsive-320..1200/td-content-1600/WC; CHẶN 1536/2048 + rogue plugin sizes. Ảnh CŨ giữ nguyên; chỉ chặn SINH MỚI khi upload → mỗi ảnh chỉ đẻ đúng bộ size cần, tránh phình uploads. (Group 5.3 "dòng WARRANTY trong box specs" của HP KHÔNG port: PDP TD dùng tab-spec khác, không có cấu trúc box specs CONDITION/WARRANTY của HP.)
Fixed · Structured data PDP - gỡ microdata Product trùng (port HP 1.9.27)
- Template PDP còn microdata (
itemscope itemtype="schema.org/Product"+itempropname/description) tạo Product thứ 2 trùng lặp cạnh RankMath JSON-LD; với SP biến thể (ProductGroup) bản microdata thiếuoffers→ Google báo invalid "phải chỉ định offers/review/aggregateRating". Gỡ 3 microdata khỏicontent-single-product.php(article/h1 name/desc - TD chỉ có ở file này, không như HP 5 file), để RankMath JSON-LD là nguồn schema Product DUY NHẤT (verify live: microdata Product 0, RankMath Product có offers). Hiển thị không đổi.
Fixed · Admin comments - review metabox + list Q&A (port HP 1.9.46)
- WooCommerce
ReviewsCommentsOverridesloại post_typeproductkhỏi mọi list-table screenedit-comments→ (1) meta box "Đánh giá" trên trang SỬA sản phẩm rỗng (spinner quay hoài dù SP có review), (2) trang Comments lọccomment_type=td_qna(câu hỏi Q&A gắn product -inc/qna.php) rỗng, không moderate được (link email báo câu hỏi mới trỏ đúng vào đây). Thêm filtercomments_list_table_query_args@20 (sau WC @10): bỏ ràng buộcpost_typekhi query nhắm 1 post_id LÀ product (metabox) hoặc khitype=td_qna. Trang Comments chung vẫn giữ hành vi loại product của WC. (Bug 1 của HP - whitespace trước<?phpphá XML replyto-comment - KHÔNG áp dụng: quét 0 file TD có output trước<?php.)
Added · Filter UX (toolbar + CSS) - cặp với plugin tandoanh-code 6.8.0
- Toolbar shortcode
[td_shop_toolbar](inc/woo/woocommerce.php) thêm 3 phần tử phục vụ Filter UX mới:.td-shop__toolbar-count(tổng số kết quả, render server-side từ$wp_query->found_postsđể không CLS; JS filter cập nhật khi lọc AJAX),.td-sort-open(nút mở bottom-sheet Sắp xếp - chỉ mobile, JS dựng sheet từ<select class="orderby">native), badge.td-filter-btn__count(số bộ lọc đang chọn) trong nút Lọc. - CSS Filter UX in INLINE ở
wp_head(#td-filter-ux-css, chỉ trang shop/category/tag/tax/search) để né PurgeCSS - giống patterntd-backorder-css. Style active-chips/sort-sheet/empty-state/count/badge dùng token theme (--td-brand/--td-surface/--td-line/--td-text/--td-radius-lg/--td-font-display); muted text dùngcolor-mixtừ--td-text(theme không có--td-muted) để tự thích ứng light/dark. Mobile ẩn native<select>hiện sort-sheet trigger; desktop ngược lại. Logic JS ở plugin (filter-r3.js).
[1.9.13] - 2026-08-23
Fixed · Vòng review mã (trạng thái kho onbackorder)
- Card SP
onbackorderKHÔNG còn nút "Mua ngay"/thêm giỏ (WooCommerce coi onbackorder = in stock nên card cũ vẫn cho mua thẳng → trái spec). Nhánh CTA card (content-product.php) nay ưu tiên$is_backorder→ nút "Liên hệ đặt trước" (link PDP), khớp buybar PDP. - Buybar backorder chỉ thay
form.cartcho SP KHÔNG phải variable (! is_type('variable')) - tránh SP variable (mọi biến thể backorder) bị mất bộ chọn biến thể; SP variable rơi về form chuẩn để chọn biến thể như cũ. (Đổi động header/buybar theo biến thể vẫn ở Tier B.) td_contact_url()thêm filtertd_contact_urlđể override trang Liên hệ (slug khác / cấu hình) thay vì hardcode cứng. Bump 1.9.12 → 1.9.13.
[1.9.12] - 2026-08-23
Added · Trạng thái kho đầy đủ 4 mức + "Hàng đặt trước" (port HP 1.9.36/1.9.49/1.9.50)
- Dòng trạng thái kho header PDP (cạnh rating) phản ánh đủ 4 trạng thái:
instock→"Còn hàng" (xanh lá),onbackorder→"Hàng đặt trước" (xanh dương),outofstock→"Hết hàng" (mờ),ngungkd→"Ngừng kinh doanh" (cam). Helpertd_stock_header_meta()+ map 4 trạng thái quadata-td-stock-labels(chuẩn bị Tier B đổi động theo biến thể). - Trạng thái
onbackorder"Hàng đặt trước" - TÍCH CỰC: vẫn hiện SP, GIỮ vị trí list (sort onbackorder=1), KHÔNG làm mờ, nhưng ẨN nút mua và hiện nút "Liên hệ đặt trước" (link trang Liên hệ); card shop badge xanh. Helpertd_stock_is_backorder()+td_contact_url();.td-buybar--backorder/.td-btn-backorder/.td-pcard__backorder-flag; CSS inline wp_head chống PurgeCSS. Bump 1.9.11 → 1.9.12. - CÒN LẠI (Tier B): cập nhật động header+buybar khi đổi biến thể (thêm data-stock vào card biến thể plugin tandoanh-code + JS applyStockState).
[1.9.11] - 2026-08-23
Added · Tự cập nhật self-hosted qua phatdev.net
- Thêm updater riêng (
inc/theme-updater.php, classTD_Theme_Updater) kiểm trahttps://phatdev.net/api/updates/tandoanhvà hiện bản mới ở màn Cập nhật WordPress, tải gói từ update server có license. Cầndefine('TD_UPDATE_LICENSE', '...')trong wp-config.php; thiếu key thì im lặng (no-op). Gói ZIP chỉ phục vụ license hợp lệ active; server log + rate-limit theo IP; manifest cache 6h, xoá sau khi cập nhật.
[1.9.10] - 2026-08-11 (Hết hàng / Ngừng kinh doanh - ẩn nút mua + đánh dấu + đẩy cuối list)
Đồng bộ hành vi SP/biến thể hết hàng (outofstock) + ngừng kinh doanh (ngungkd) theo bản HP.
- Đăng ký lại custom stock status
ngungkd(port production flatsome-child - theme mới thiếu → admin mất option + nhãn): filterwoocommerce_product_stock_status_options+woocommerce_admin_stock_html. Helpertd_stock_is_oos()/td_stock_oos_label(). - Ép
is_in_stock()= false chongungkd(filterwoocommerce_product_is_in_stock). WC vốn tínhis_in_stock = ('outofstock' !== stock_status)nên ngungkd bị coi CÒN HÀNG (mua được, card ra "Mua ngay", rating "Còn hàng"). Nay ngungkd xử lý như hết hàng mọi nơi. - PDP (
content-single-product.php): SP hết hàng/ngừng KD → thaywoocommerce_template_single_add_to_cart()bằng 1 nút dài "Sản phẩm hết hàng"/"Ngừng kinh doanh" (.td-btn-oos, đọc rõ light+dark). Variable còn hàng 1 phần: WC native tự khoá nút theo biến thể (td chỉ 1 SP mixed). - Card (
content-product.php+woo-card.css): ảnhgrayscale(1)+ nhãn to giữa ảnh 1 hàng (.td-pcard__oos-flag, slate=hết hàng / cam#b45309=ngừng KD, đạt AA), ẩn badge-%khi hết hàng; actions ra "Xem chi tiết". - Sort: định nghĩa
move_outofstock_and_ngungkd_to_endtrong theme (plugin tandoanh-code fast-filter GỠ đúng tên hàm này) → instock/onbackorder → outofstock → ngungkd cuối, đúng qua phân trang (test card-do-hoa-nvidia trang 28-29 toàn ngungkd). - CSS sửa cả bản
.purged. A11y=100/BP=100/CLS=0. td dùng WC add-to-cart native nên KHÔNG có lỗi"như HP. - Review hardening: sort
move_outofstock_and_ngungkd_to_endbỏ nhánhDOING_AJAXchết + guard orderby rỗng (tránh trailing-comma vỡ SQL). Xác nhận setting hide-out-of-stock=off, 0 variable ngungkd. - Fix pre-existing (phát hiện khi review): card SP variable nút "Mua ngay" trước trỏ
add-to-cart={parent_id}(thiếu variation_id → checkout lỗi/giỏ trống, 76 SP dính) → nay variable → PDP để chọn cấu hình; simple giữ mua thẳng.
[1.9.9] - 2026-07-20 (Landing: tách SVG scene build-card ra <img> ngoài - giảm DOM 45%)
Bối cảnh: 3 landing mobile kẹt 84-86 vì nghẽn CPU/DOM (gaming 5.513 phần tử, riêng section builds 2.690 = 49% do 5 SVG scene inline vẽ máy tính). Đo kỹ đã chứng minh không nghẽn mạng.
Làm: script tách SVG tách 5 SVG scene trong .build-img của mỗi section builds (bake HTML inc/blocks/registry/land-section/sections/{gaming,ai,creator}-builds.html) ra file assets/landing-svg/{variant}-build-{n}.svg, thay inline <svg> bằng <img class="build-img-svg" loading="lazy" decoding="async" width="720" height="720">. GIỮ NGUYÊN vector + SMIL <animate> (SMIL vẫn chạy trong <img>), KHÔNG đổi sang WebP/AVIF. Bỏ ~7.672 thẻ khỏi DOM (gaming 5.513→3.052).
GOTCHA quan trọng (bắt khi review): SVG ai/creator dùng var(--accent/--bg-1/--ink-3…) trong presentation attribute fill=. var() CHẠY khi SVG inline (Chrome resolve) nhưng KHÔNG chạy trong <img> external (document cô lập) → mọi phần tử var-màu biến mất (đen trên đen - suýt lọt vì nhìn cỡ nhỏ). Đã bake giá trị biến thật vào file SVG (bake_vars() trong generator). An toàn vì landing KHÔNG có override [data-theme=dark] cho các biến này (scene màu cố định). A/B inline vs baked-external: khớp 100%.
Kết quả (median 5 lần, Lighthouse):
- gaming: 86→86 (SVG màu inline, externalize trung tính nhưng DOM -45%, TBT 101→26ms headroom)
- ai: 94→97 (+3 - bỏ var() presentation attr đắt style-recalc)
- creator: 81→82 (ngang, DOM 1.201→~200)
- Hero SVG (gaming) GIỮ inline: JS (landing-pc-gaming.js) chèn
<animate>+ cập nhật telemetry qua querySelector → external<img>sẽ phá hiệu ứng.
Lưu ý: sections/*.html là file bake render.php đọc trực tiếp. Sửa trực tiếp ở đây; nếu re-bake từ landing-clone thì SVG inline quay lại - chạy lại script tách SVG. A11Y/BP giữ 100 (img alt="" cho ảnh trang trí).
[1.9.8] - 2026-07-20 (PSI round: Accessibility + Best Practices = 100 toàn site)
Đo lại toàn bộ 14 loại trang × mobile/desktop. Mục tiêu: Perf mobile ≥95, desktop ≥98, A11Y=100, BP=100 (bỏ qua SEO - staging cố ý Disallow).
Best Practices 78-79 → 100 (cart, tìm kiếm, liên hệ)
- Bug thật:
delay_third_partychỉ chạy trongwpfc_buffer_callback_filter, mà WPFC KHÔNG chạy buffer trên trang nó không cache (giỏ hàng, tìm kiếm, tài khoản). Đúng 2 trang đó nạpgtag/jsngay → 1 long task 551-583ms = gần trọn TBT 650-670ms → PERF mobile 82, BP 79. Các trang có cache đều 95-99/BP 100. - Fix (
inc/speed.php): thêmtemplate_redirect(priority 0) tựob_start()áptandoanh_speed_delay_third_party()cho CHÍNH các trang WPFC bỏ qua. GIỮ tracking (chỉ dời thời điểm nạp tới lúc tương tác/12s). Buffer này CHỈ áp cho cart/account/search - vì nó xả TRƯỚC buffer WPFC nên nếu áp trên trang có cache sẽ bị WPFC minify nuốt mấttype="td-delayed-src"→ GA không bao giờ chạy (đã đo & suýt hỏng tracking trang chủ, đã thu hẹp lại). - Regex delay làm idempotent (
([^>]*\s)src=để không khớpdata-td-src=của chính mình) → chạy nhiều lần vô hại. - Kết quả: cart mobile 82→99, timkiem 82→99, cả 3 (+lienhe) BP 78-79→100. TBT 650ms→0ms. GA vẫn chạy sau tương tác (đã verify bằng Chrome cả trang cache lẫn không cache).
reCAPTCHA v3 - BP liên hệ desktop 78 → 100 (plugin tandoanh-code 6.7.5 + 6.7.6)
- Cookie bên thứ ba của reCAPTCHA (
api2/reload) làm BP desktop 78 (mobile không dính vì form xa viewport hơn rootMargin 200px). Hoãn LẮP IntersectionObserver tới sau tương tác đầu → bot/Lighthouse không nạp, khách thật vẫn tải sớm. - Review mã phát hiện race (Trung bình): nếu khách bấm Gửi trước khi api.js kịp tải → token rỗng → server chặn nhầm khách. Đã thêm submit-guard: token rỗng lúc submit thì chặn đúng lần đó, lấy token xong mới gửi lại; fail-safe 20s. Verify: token field 0→2105 ký tự trước khi POST thật.
Accessibility - creator-studio desktop 96 → 100 (assets/css/landing-enhance.css)
- 3 chỗ contrast còn sót: (a)
.cr-swatch spanclone có rule (0,3,1)+!important thắng fix cũ (0,2,1); (b).cr-filmtag-ltrước đây bỏ sót (chỉ sửa.cr-filmtagcha +-r); (c) tab.activemục Discipline dùng--accent-100#8a6410 = 3.19. - Bài học: KHÔNG chỉ set
-webkit-text-fill-color- trình duyệt vẽ theo fill nên mắt thấy đúng nhưng axe của Lighthouse đọccolor→ vẫn fail. Phải set đúngcolorvới specificity đủ thắng.
Đã THỬ & BỎ (ghi để không lặp lại) - landing mobile 84-86
- Critical CSS riêng landing (sinh từ trang thật, giữ trọn hiệu ứng): bỏ render-blocking, FCP 3,2→1,7s nhưng LCP đứng yên, CLS nổ 0,998 → PERF 46.
- content-visibility (đo chiều cao thật từng section, trung vị 5 lần): main-thread 11,2→9,3s nhưng TBT 101→257ms, net âm 5đ.
- Nguyên nhân gốc: landing KHÔNG nghẽn mạng (CSS xong 221ms, font 428ms) mà nghẽn CPU - main-thread 11,2s, styleLayout 3,4s, DOM 5.513 phần tử (riêng section builds 2.690 = 49% do 5 SVG inline). Đòn bẩy duy nhất còn lại: thay SVG inline → ảnh WebP/AVIF (cần duyệt vì đụng thiết kế).
Ghi chú p404
- Lighthouse chấm 0 điểm trang 404 vì
ERRORED_DOCUMENT_REQUEST(từ chối chấm mọi trang trả HTTP 404). Đây là hành vi ĐÚNG của trang 404, KHÔNG phải lỗi site. Đã bỏ p404 khỏi suite đo.
[BRAND MIGRATION] - 2026-07-20 (Retire pa_thuong-hieu → product_brand toàn site + sync tự chuyển)
Không phải thay đổi theme (nằm ở plugin + script sync), ghi lại đây vì ảnh hưởng filter toàn site.
Bối cảnh: bản thử là bản sao một chiều của bản chính thức; bản chính thức lưu thương hiệu ở attribute pa_thuong-hieu, bản thử đã dùng taxonomy product_brand. Trước đây 2 cái tồn tại song song (dữ liệu trùng), mỗi lần sync production lại đẩy pa về.
Thứ tự làm (quan trọng - làm sai thứ tự là gãy filter):
- Sync bình thường trước (116 SP thay đổi, reconcile 24, 0 lỗi).
- Migrate bộ lọc Build PC sang
product_brandTRƯỚC KHI strip - phát hiện Build PC vẫn sinh bộ lọc "Thương Hiệu" từ registry attribute WooCommerce, nếu strip trước thì bộ lọc rỗng. Thêm helperbp_attr_taxonomy()(tandoanh-buildpc/includes/class-ajax.php) mapthuong-hieu→product_brand, áp cho 7 chỗ dựng taxonomy (list filter, faceting, query, dependency, endpoint gộp). GIỮ key UI/JSthuong-hieunên không phải sửa frontend. - Strip 1 lần: 3.374 SP gỡ
pa_thuong-hieu+ dọn_product_attributes. Dry-run trước cho thấy 100% SP đã cóproduct_brand→ 0 rủi ro mất brand. Còn lại 0 SP mang pa. - Sync tự chuyển từ nay: sửa cả 2 converter của bước đồng bộ - convert pa→brand rồi GỠ pa.
Nơi khác đọc brand đã kiểm/sửa: filter danh mục (index product_brand, an toàn) · PDP (product_brand chính, pa chỉ fallback) · Google Shopping (đã product_brand) · buildpc/ai/class-ai-index-manager.php extract_brand() (SỬA: đọc product_brand trước, không thì AI index mất brand).
Review mã bắt thêm 6 điểm - đã sửa hết:
- [High]
wp_ajax_hp_sync_one(sync THỦ CÔNG từ UI admin) không gọi converter → pa quay lại. Đã gọihp_sync_convert_brand()sau import. - [High] 2 converter không kiểm kết quả
wp_set_object_terms()mà đã gỡ pa → có kịch bản MẤT brand thật. Đã ĐỌC LẠI TỪ DB xác nhận brand gắn thành công rồi mới gỡ. - [Med] Logic "đã có brand thì thôi map" giữ brand SAI vĩnh viễn khi production đổi hãng. Đã so slug nguồn vs hiện tại, khác thì đồng bộ lại.
- [Med]
compute_filters_data()còn dựng'pa_' . $aname(biến khác nên lệnh thay đồng loạt SÓT) → endpoint gộp lọc sai sau migrate. Đã route qua helper. - [Low] Dọn meta tách khỏi điều kiện taxonomy pa còn tồn tại.
- [Low] Label filter fallback
Thương Hiệukhi taxonomy làproduct_brand.
Gán brand cho SP thiếu: 36 SP publish không có brand → suy brand từ tên (ưu tiên khớp 166 term có sẵn, máy bộ "TD ..." ưu tiên tuyệt đối = Tân Doanh). Gán 19 SP, còn 17 là hàng generic thật (cáp, keo tản nhiệt, kìm cắt ống, ly nước) cố ý để trống. GOTCHA đã tránh: HP khớp nhầm trong "HPCT", và "PC TD (…Gigabyte X870E…)" suýt bị gán Gigabyte thay vì Tân Doanh.
Verify sau cùng: filter danh mục 24/24 đúng AMD · Build PC lọc amd 69 / intel 50, 0 lẫn hãng, endpoint gộp 16/16 đúng · PDP kicker hiện brand · pa_thuong-hieu = 0 term/0 SP · PHP log trống.
[1.9.7] - 2026-07-16 (Review mã VÒNG 2 - siết tiếp 6 điểm, gồm 3 lỗi mới)
Chạy review mã vòng 2 để (a) kiểm chứng 7 fix của 1.9.6, (b) review code mới 1.9.5, (c) quét vùng vòng 1 chưa đụng. Review mã xác nhận fix 1,2,3,4 ĐÚNG (thử bypass SSRF bằng evilgoogle.com, docs.google.com.evil.com, userinfo @, IDN - đều không lọt), nhưng 5,6,7 chưa kín + tìm thêm 3 lỗi mới. Đã sửa:
- [BUG THẬT - code mới 1.9.5]
inc/landing.php/build-price:array_unique($ids)làm rơi linh kiện trùng mã → cấu hình có 2 thanh RAM cùng loại bị tính THIẾU giá. Bỏarray_unique. Verify: 1 thanh = 60.990.000 (n=1), 2 thanh = 121.980.000 (n=2). - [Med] 2 REST public chưa throttle:
/prices+/build-price(__return_true,/wp-jsonkhông ăn page cache → đổi querystring là ép chạywc_get_productlặp). Thêm throttle 120 req/phút/IP đếm atomic, trả 429. - [Med]
assets/js/blocks.js: 2 chỗdangerouslySetInnerHTMLnhéttitle.rendered/nameMapvào DOM → XSS phía editor khi mở ProductPicker. Đổi sang text node (React tự escape) + helpertdDecodeEntities()dùng<textarea>(RCDATA, không parse thẻ) để tên vẫn hiện đúng dấu&. - [Med] Rate-limit AJAX (1.9.6) chưa chắc:
get_transient+set_transientkhông atomic (race đếm sai) + off-by-one (>40lọt request 41) + dễ chặn oan khách chung IP. Đổi sangwp_cache_add+wp_cache_incr(atomic trên Redis), ngưỡng 120/phút (rộng cho NAT/4G), tự bỏ qua nếu không có persistent object cache. - [Low]
inc/woo/pdp.phpsafeUrl(): còn lọt protocol-relative//evil.comvì regex nhận mọi chuỗi bắt đầu/. Siết^(?:\/(?!\/)|https?:\/\/). Verify://evil.com→#,/pathvàhttps://td...vẫn qua. - [Low]
inc/woo/woocommerce.phptd_add_build: check referer fail im lặng (khách bị strip Referer bấm xong giỏ trống, không hiểu vì sao). Đổi thành redirect kèmwc_add_noticebáo rõ.
Đã kiểm chứng và BÁC một phần finding của review: Review mã nói buildband cũng nên bỏ array_unique để giữ qty - nhưng tandoanh-buildpc/includes/preload.php:68 set $selected[$step_id][$pid] = 1 (qty cứng 1), nên ID trùng bị gộp bất kể array_unique. Bỏ ở buildband không đổi gì → giữ nguyên. (Giới hạn qty=1 của builder là hạn chế sẵn có của plugin, đã ghi ở 1.9.5.)
Chưa làm (chấp nhận): tools/*.py parser tự chế "giòn" (Low) - chỉ là tool build chạy tay lúc dev, không phải code runtime khách chạy; sửa = viết lại parser, chưa đáng.
[1.9.6] - 2026-07-16 (Fix 7 phát hiện từ Review mã theme - bảo mật + hiệu năng)
Chạy Review mã toàn theme. Không có Critical/RCE/SQLi/path-traversal; nền tảng ổn (form admin có nonce+capability). Sửa 7 mục đáng làm (mỗi mục đã tự kiểm chứng là thật, không phải false-positive):
- [High]
inc/blocks/registry/newsband/render.php:wp_remote_get('sslverify'=>false)→ bật lạitrue(chống MITM nội dung tin nhúng vào site). - [Med]
inc/woo/checkout.php: bug cache tra MST - ghi transient'none'(string) nhưng đọc chỉ nhậnis_array→ MST sai vẫn bắn HTTP raapi.xinvoice.vnmỗi lần gõ. Thêm nhánh đọc sentinel'none'→ short-circuit, hết gọi ngoài thừa. - [Med]
inc/buyback-pricelist.php: SSRF -normalize_csv_url()trả URL tuỳ ý (từ shortcode/option) rồiwp_remote_get. Thêm whitelist host (docs.google.com/googleusercontent.com/google.com), host lạ → rơi về nguồn mặc định. - [Med]
inc/qna.php: N+1 (20 câu hỏi = 21 query). Gom TẤT CẢ answer 1 queryparent__inrồi group theocomment_parenttrong PHP (giữ hành vi lấy answer mới nhất). - [Med]
inc/woo/woocommerce.php:?td_add_build=thêm ≤15 SP vào giỏ qua GET không nonce → nhét giỏ CSRF. Thêm check same-origin referer (hợp cache tĩnh, không cần nonce; luồng add-to-cart chính của builder vốn đã có nonce AJAX). - [Low]
inc/product-section-more.php+inc/top-row.php: AJAX publictd_psec_more/td_tb_morekhông nonce (cố ý vì cache) → thêm rate-limit 40 req/phút/IP (transient) chống spam đốt PHP/DB. - [Low]
inc/blocks/registry/buildband/render.php:maybe_unserialize($raw, [...])- WPmaybe_unserializeKHÔNG nhận$optionsnênallowed_classes:falsebị bỏ qua. Đổi sangunserialize($raw, ['allowed_classes'=>false])sauis_serialized()→ chặn object injection thật. - [Low]
inc/woo/pdp.php: "Sản phẩm vừa xem" dựnginnerHTMLtừ localStorage (DOM-XSS sink). Đổi sangcreateElement+textContent+ guard scheme URL (chặnjavascript:).
Ghi chú: review chạy ở chế độ chỉ-đọc. Fix toàn code CŨ của theme (không đụng landing/config 1.9.5).
[1.9.5] - 2026-07-16 (Build card 3 landing = CẤU HÌNH THẬT, mở editable ở Build PC, giá tổng live)
Trước đây 5 build card mỗi landing chỉ là placeholder: link tới 1 SP PC dựng sẵn, giá cứng; creator bị COPY NHẦM toàn bộ config AI (tên PHOTO/EDIT nhưng trỏ ai-top-atom/100/500). Yêu cầu: soạn cấu hình THẬT từ linh kiện rời, mở sửa được ở Build PC, giá thật.
Cơ chế
- REST
tandoanh/v1/build-price?sets=id,id|id,id(inc/landing.php): trả TỔNG giá live theo từng bộ ID linh kiện (transient 5', /wp-json không được WPFC cache). Batch cả 5 build 1 request. - JS clone (landing-clone/{slug}.html → regenerate
landing-{slug}.js): mỗi build đọccfg.parts(ID linh kiện) → card/nút mở/tu-chon-cau-hinh-pc/?td_parts=<ids>(builder tự map linh kiện vào step + editable + giá live) ;.now= tổng /build-price (giá cứng chỉ là fallback hiện ngay). Giữ nhánh slug cũ làm fallback. - Script chèn linh kiện: chèn
"parts":[ids]vào từng build trongvar TDCFG(parser cân bằng ngoặc, idempotent). Sửa TDCFG/soạn lại config = sửa clone rồi chạy lại script dựng landing.
15 cấu hình thật (soạn từ catalog, mọi ID in-stock + đúng socket/PSU + đúng danh mục builder, verify từng cái)
- Gaming: FOX 26.8tr · WOLF 31.7tr · TIGER 50.3tr · EAGLE 65.9tr · DRAGON 200tr (i5-13400F→Core Ultra 9 285K, RTX 3060→5090).
- AI: INFER 56.8tr · ATOM 241tr · TRAIN 307tr · QUAD 384tr · XEON 807tr (Core Ultra/Ryzen→Threadripper Pro 7995WX + RTX 5090/RTX PRO 6000 96GB + RAM ECC-R).
- Creator (soạn MỚI đúng chất sáng tạo, hết copy AI): PHOTO 48tr · EDIT 70tr · COLOR 109tr (ProArt) · STUDIO 280tr · MASTER 395tr (Ryzen/Threadripper + RTX 4070S→5090).
- Giá là GIÁ THẬT theo catalog TD (cao hơn giá marketing cũ ở tier AI/creator cao vì 5090 ~124tr, RTX PRO 6000 ~400tr, TR Pro ~108-260tr).
- Giới hạn builder: nạp 1 SP/step (qty 1) → tier RAM cao (128/256/512GB ECC) hiện nạp 1 thanh 64GB, khách tự tăng số lượng trong builder. Spec text trên card giữ định vị đầy đủ.
- Verify live: 3 landing card đều CTA→builder + giá tổng đúng; mở TD-INFER (?td_parts=8 ID) → builder nạp đủ 8 linh kiện, editable, tổng 56.820.000₫ khớp card; 0 lỗi console.
[1.9.4] - 2026-07-13 (Trang tài khoản: bỏ hạng thành viên GIẢ, thay bằng data THẬT từ WooCommerce)
Phát hiện trang My Account hiện "THÀNH VIÊN GOLD · 7.250/10.000 điểm · lên hạng Platinum · giảm thêm 5% mọi đơn + giao siêu tốc miễn phí 6 tháng" - toàn bộ HARDCODE BỊA (mọi khách thấy y hệt), KHÔNG có plugin điểm/loyalty active, KHÔNG có code áp giảm 5% ở đâu → hứa hão với khách. (Đồ mockup bê từ Hưng Phát 2026-07-01, chưa thay data thật.)
- Port cách HP đã sửa (
woocommerce/myaccount/my-account.php): bỏ khối hạng + điểm + lời hứa giảm giá, thay bằng 3 ô stat THẬT:- Số đơn hàng -
wc_get_customer_order_count() - Đã chi tiêu -
wc_get_customer_total_spent()(rút gọn "X tr"/"Xk") - Thành viên từ - năm đăng ký
- Badge hạng → "Đã tham gia N năm" / "Thành viên mới" (tính từ
user_registered), icon lịch thay icon huy chương.
- Số đơn hàng -
- CSS: bỏ
.acc-tier-progress(thanh điểm giả), thêm.acc-stats/.acc-stat(port HP, giữ token gold td) + responsive mobile. - Verify (user 3276 thật: 0 đơn/0₫): hiện "Đã tham gia 7 năm · 0 Đơn hàng · 0₫ · 2019", đồ giả Platinum/7.250/giảm 5% đã biến mất, desktop + mobile không tràn, 0 lỗi.
[1.9.3] - 2026-07-13 (Fix logic bench + tier-tab + nút × FAQ - cả 3 landing)
Báo cáo 3 lỗi tương tác (đều từ JS clone giả - viết cho gaming rồi copy sang, số fake random). Fix trong landing-enhance.js/.css (chạy trên bản block live, config theo variant).
- Bench - tab category không lọc + số random: mọi
.fps-pillchạy CHUNG handler clone → repaint số RANDOM cho tất cả dòng, category (LLM/Diffusion/Audio/Video) không lọc (bấm Diffusion vẫn hiện Llama = vô lý). Fix: cloneNode gỡ handler cũ, bind lại - category pill LỌC dòng thật (LLM→3 dòng LLM, Diffusion→SD/SDXL/Flux, Audio→Whisper, Video→Mochi), build pill đổi số DETERMINISTIC theo hệ số build (yếu→mạnh), hết random. Map row↔category per variant (ai/gaming/creator). - Builds tier-tab "bấm tab khác mất hết": filter clone chỉ khớp keyword
esport/streamer/4k(của gaming) → tab AI Inference/Training/Enterprise + creator không khớp → ẩn sạch card. Fix: map tab→card-index theo variant (ai: Inference[0,1]/Training[2]/Enterprise[3,4]) → mỗi tab luôn hiện đúng card. - Nút × FAQ xấu: toggle là dấu
+(SVG) xoay 45° thành×+ nền gold ĐẬM. Đổi (CSS) thành chevron (ẩn SVG, vẽ::after; đóng=xuống/mở=lên, vòng gold NHẠT). Gọn, chuẩn accordion.
Verify cả 3 landing: category lọc đúng row (creator Photo=Lightroom+Photoshop…), build số deterministic (314==314), tier-tab không tab nào 0 card (gaming eSports:2/Streamer:1/4K:2; creator 4 tab đều >0), FAQ chevron xoay đúng, 0 lỗi JS.
[1.9.2] - 2026-07-12 (Landing live chuyển MẶC ĐỊNH sang bản block)
3 landing bespoke (pc-gaming / ai-workstation / creator-studio) trước đây khách xem inline clone (filter the_content đọc inc/landing-inline/{slug}.html); bản block chỉ preview qua ?td_blocks=1. Bản block đã khớp 100% clone (desktop 1440 + mobile 390, 0px lệch) và edit được như homepage → giờ đảo thành mặc định.
inc/landing.php- flip mặc định: filterthe_contentgiờ early-return$content(renderpost_content= các blockland-hero/land-section) cho MỌI khách. Nhánh inline clone GIỮ NGUYÊN làm rollback/đối chiếu, opt-in qua?td_inline=1(cờ cũ?td_blocks=1bỏ - không còn cần).- Không đụng markup/CSS/JS: block path đã tự lo full-bleed (template
page-{slug}.htmlgắn.td-main.tdp-landlayoutdefault), subnav sticky (gaming/creator bake sẵn.td-subnav, AI dựng từnavLinkscủaland-hero), terminal-hide (land-hero render.php echo ở frontend), enhance CSS/JS (enqueue chung cả 2 path). - Verify: 3 URL mặc định (không query) trả 200,
tdp-land-inline=0, đủ 7/8/9 land block + subnav; screenshot desktop 1440 full-bleed đúng cho cả 3.
Đồng bộ tên build (fps-pill + bảng so sánh) từ TDCFG - hết lệch data
- Vấn đề: build card lấy tên THẬT từ
TDCFGtronglanding-{slug}.js(AI:TD-INFER/ATOM/TRAIN/QUAD/XEON; creator:TD-PHOTO/EDIT/COLOR/STUDIO/MASTER), nhưng pill chọn build ở section benchmark VÀ header bảng so sánh vẫn giữ tên placeholder cũ của clone (AI:TD-OTTER/FALCON/ORCA/…; creator:TD-AMBER/COPPER/…) → khách thấy 3 tên khác nhau cho cùng 1 máy. - Fix (nguồn duy nhất = TDCFG): thêm bước đồng bộ trong script clone (
landing-clone/{slug}.html, sau vòng áp TDCFG vào build card) - pill có text bắt đầuTD-(KHÔNG đụng pill categoryAll/LLM/Diffusion/…) + ô.compare-table .tiernhận đúng tên build theo vị trí. Regenerateassets/js/landing-{slug}.jsbằng script dựng landing. Sửa TDCFG 1 chỗ → card + pill + compare theo hết. - Gaming đã nhất quán sẵn (
TD-FOX/WOLF/…baked khớp TDCFG) → bước sync idempotent, không đổi gì. - Verify live (bản block, không query): AI + creator + gaming đều khớp 3 chỗ (pill = compare = card); pill category + tier label giữ nguyên; click pill vẫn toggle active + repaint FPS bar; JS
node --checksạch, 0 lỗi console.
Sửa chữ editable cho hero (gaming/creator) + mọi section-head - override an toàn, zero regression
- Vấn đề: hero gaming/creator + tất cả section-head bake nguyên trong
land-section(editor chỉ chọn variant/section, không sửa chữ được). Hero AI thì đã editable qualand-hero. 2 hero gaming vs creator cấu trúc bespoke KHÁC NHAU (.hero-inner/.hero-dividervs.cr-hero-*) → dựng lại từng hero trong PHP = rủi ro regression cao trên trang vừa lên live. - Cách làm (thống nhất + an toàn): thêm 3 attribute override
ovEyebrow/ovTitle/ovLeadcholand-section. Render giữ NGUYÊN 100% markup + SVG scene bake, chỉ đè nội dung phần tử đầu tiên có class.eyebrow/.h-display|.h-section/.leadbằng helpertandoanh_land_replace_inner()- quét cân bằng theo tên thẻ (không cắt sai khi có thẻ con cùng tên), KHÔNGpreg_replace(tránh backreference trong nội dung). Rỗng = giữ nguyên bản gốc → mặc định không đổi gì. - Điểm ăn: mọi section-head đồng nhất
.eyebrow+.h-section+.lead; cả 3 hero (gaming/creator/AI) đều.h-display→ 1 cơ chế phủ hero headline lẫn tiêu đề/phụ đề mọi section. - Editor
land-section: bỏ Notice "bản sau", thêm panel "Sửa chữ (đè clone)" với Eyebrow (TextControl) + Tiêu đề/Mô tả (TextareaControl, cho HTML<span class="gold">/<br>); ServerSideRender preview đè đúng. Buildnpm run build(wp-scripts) - compiled sạch. - Verify: 12/12 test
do_blocksPASS - override eyebrow/title/lead đúng, bản KHÔNG override byte-identical với bake gốc (0 regression), SVG scene + subnav + hero-divider + fps-pill nguyên vẹn; 3 trang live vẫn 200, marker đủ. - CÒN increment nhỏ (chưa làm, ít giá trị/hiếm sửa): override nhãn NÚT hero (giữ SVG mũi tên) + số liệu STAT hero (gold+suffix+sao) - cấu trúc lặp/đặc thù, tách sau nếu cần.
Tách seasonal.css per-preset - nạp ~15KB thay vì 60KB khi bật mùa
assets/css/seasonal.css(60KB, 8 mùa gộp) là NGUỒN; thêm script tách sinhseasonal-shared.css(8KB, rule dùng chung[data-preset] …+ keyframes) +seasonal-{preset}.css(5-8KB, var line/accent/motif-SVG +.td-sfx i+body::before/aftercủa riêng mùa đó). Selector gộp nhiều preset (vd dark noel+dong) nhân bản vào từng file liên quan - integrity 62 vs 59 rule-brace đúng như dự kiến.inc/admin/seasonal.phpenqueueseasonal-shared.css+ CHỈseasonal-{active}.css(fallback monolith nếu chưa sinh split). Scene inline CSS (side-strip SVG) cũng scope về đúng preset đang bật (trước lặp cả 8 mùa).- Verify: bật
tet→ chỉ nạpseasonal-shared.css+seasonal-tet.css(KHÔNG noel, KHÔNG monolith); tắt preset → 0 CSS seasonal (ngày thường 0 chi phí PSI giữ nguyên); braces các file split cân bằng; PHP lint sạch. - Sửa trang trí mùa: sửa
seasonal.cssrồi chạy lại script tách.
FIX bảng so sánh landing: viền trắng #ececec leak từ block-library (góc bo gãy + line dọc lệch)
- Triệu chứng: bảng so sánh 3 landing bo góc bị "mất đường line trắng" ở góc.
- Root cause: post_content 3 landing chứa block (land-section) → WP
wp-block-librarynạp CSS bare-elementtable{border:1px solid #ececec}+td{border-right:1px solid #ececec}(áp toàn cục, CÓ trên cả path block lẫn?td_inline=1- không riêng block). Clone CHỦ Ý.compare-tableKHÔNG viền ngoài (dựa.compare-cardoverflow:hidden+border-radius:20px) và cell CHỈborder-bottom. → (a) viền vuông #ececec bị góc bo clip = gãy đường ở góc; (b)tdcó viền phải trắng màthkhông = line DỌC trắng lệch, sai màu, không có trong clone gốc. - Fix (landing-enhance.css, scope
[class*="tdp-land-"], specificity 0,2,0-1 > bare element):.compare-table{border:0}- bỏ viền ngoài (hết gãy góc)..compare-table td,th{border-top:0;border-right:0;border-left:0}- bỏ viền dọc/đỉnh leak, GIỮborder-bottomcủa clone → chỉ còn line NGANG, khớp clone gốc landing.tandoanh.vn.
- Đồng thời QA quét CSSOM toàn landing tìm rule leak nguồn ngoài (bare element/
.wp-*/.entry-*) áp vào.tdp-land-*: chỉ 4 hit - 2 vô hại (*{box-sizing},a{color}- nút.build-ctamũi tên đậm trên nền gold ĐÚNG contrast), 2 đã fix trên. 0 lỗi console. - Verify live: computed
.compare-tableborder=0, cell border-right=0, border-bottom giữ line ngang; screenshot AI + gaming sạch; tên build vẫn đúng INFER/ATOM/…
[1.9.1] - 2026-07-10 (Audit Security + Performance theme 1.9.0 - 3 agent song song, tự kiểm chứng)
Audit lại toàn theme sau đợt dựng lại landing bằng block (nhiều code mới từ 1.7.9). 3 agent độc lập (security runtime / security baked-content+JS / performance), mọi finding TỰ KIỂM CHỨNG lại trước khi kết luận.
Bảo mật - KHÔNG có lỗ hổng critical/high/medium
- Path traversal AN TOÀN:
land-section/render.phpghépsections/{variant}-{section}.htmlvớivariant+sectionđều quasanitize_key+ whitelist cứng 2 lớp → không chèn được../.terminal-ai.html/scenes/{variant}.htmltương tự. - XSS AN TOÀN: mọi echo attribute escape đúng (
esc_html/esc_url/esc_attr);titleHtml/branddùngwp_kses_post(block attr, cầnedit_posts). Inline hide-script tĩnh, không nội suy input. - Baked HTML sạch: 0 onclick inline (né đúng lỗi wptexturize cũ), 0
<script>lạ, 0javascript:/on*handler. - JS sạch: terminal + CTA + subnav dùng
textContent; giá LIVE từ REST gán bằngtextContent(dòng 119) - endpoint trả HTML độc cũng chỉ hiện dạng text.innerHTMLchỉ vớiTDCFGhardcode của dev. Khôngeval/Function. - INFO (không cần sửa): REST
tandoanh/v1/pricespublic GET nhưng chỉ lộ giá vốn công khai + transient cache;postMessage(..,'*')chỉ chạy nhánhinFrame(production inlineinFrame=false→ chết).
Hiệu năng - nền tốt, 1 fix
- [FIX] Double scroll-spy trên trang inline: script inline (landing.php) VÀ landing-enhance.js cùng bind
scroll+getBoundingClientRecttrên.td-subnav→ 2× layout-read mỗi scroll. Gọn lại: script inline CHỈ dựng link subnav từ.header .nav, click+scroll-spy+sticky để landing-enhance.js lo (1 handler cho cả inline lẫn block). Verify: gaming inline subnav 6 link, click cuộn + active đúng, 0 lỗi. - Ghi nhận (quyết định nội dung, không phải bug):
pc-gaming.htmlinline 383KB - nặng LCP/TBT ở request cache-miss (Brotli/gzip đã giảm; WPFC cache full HTML). Editor nạp ~360KB CSS (editorStyle 3 landing) - CHỈ admin khi mở editor landing, không đụng khách. - Sạch: business-info shortcode (
td_founded/td_years_exp) static-cache + 1get_option; the_content filter early-return rẻ; không N+1/autoload rác mới; live page render 1 readfile (không phải 7-9 block như lo ngại - path block chỉ editor/?td_blocks).
Khác
- Sửa chủ sở hữu tệp
land-section/render.phpcho nhất quán; xác nhận máy chủ chặn truy cập thư mục công cụ build (không lộ build tool).
[1.9.0] - 2026-07-10 (Landing block: editor như homepage + fix nút click + taste QA nút/border)
- Editor như homepage: viết editor JS cho
land-section(chọn variant/section + ServerSideRender preview) và bổ sung field mới choland-heroAI (eyebrow/titleHtml/stats num-unit-lbl-pct/nút kiểu link). Build quawp-scripts. KhaieditorStyle= CSS clone (landing-{variant}.css) trong block.json → preview TRONG iframe editor hiển thị có style y hệt frontend. Verify: mở editor trang AI = 1 land-hero + 7 land-section, SSR render styled, 0 lỗi block. - Fix nút click (chết trên cả inline lẫn block): nút
.btnprimary ("Workload Match"/"Khám phá 5 cấu hình"/"Đặt thuê thử"…) là<button>KHÔNG href/handler (clone bắt bằng React runtime, không lọt clone tĩnh). Thêm handler ởlanding-enhance.js: map theo chữ → cuộn tới section (#workload/#bench/#builds/#compare…); nút trong promo →/lien-he/. Chạy cả 3 landing (AI/gaming/creator), 0 lỗi. - Taste QA nút/border: thêm hover/active/focus còn thiếu (
.btn-linksáng chữ + đẩy mũi tên;.fps-pill/.btn-ghostviền+chữ gold;.part-cardnhấc + viền gold + shadow tint;.workload-itemviền hover) + presstranslateY(1px)+ vòng focus gold (a11y). Đặt tronglanding-enhance.cssscope[class*=tdp-land-](không sửa CSS clone sinh ra, không leak). 0 tràn ngang cả 3 trang. - Còn treo: fps-pill (bench) hiện tên placeholder TD-OTTER trong khi build card fetch live TD-INFER - lệch data nhỏ (chưa wire fps-pill vào live). Chuyển 3 trang live inline→block: chờ duyệt.
[1.8.9] - 2026-07-10 (Phase 6 - gaming + creator dựng bằng block, cả 3 landing khớp clone pixel-perfect)
Nhân khuôn block sang 2 landing còn lại. Cả 3 (ai/gaming/creator) giờ render bằng block rời, giống clone 100% desktop + mobile.
land-sectionmở rộng: thêm sectionhero/fps/discipline/display. Scriptextract_variant.pytách hero (kèm subnav dựng từ.header .navcủa clone) + mọi section →sections/{variant}-{id}.htmlbake nguyên.- gaming (104449): hero + fps/parts/builds/compare/promo/faq. Scene PC telemetry (CPU/FPS/RAM/GPU HUD) + subnav khớp.
- creator (104451): hero + discipline/bench/display/builds/parts/compare/promo/faq. Scene DaVinci (LIFT/GAMMA/GAIN/OFFSET + timeline + render queue) + subnav khớp.
landing-enhance.js/.csstổng quát hoá: bỏ khoá cứng.tdp-land-ai→ chạy mọi variant (subnav scroll-spy cho cả 3; terminal typing + GPU bar tự giới hạn ở trang có.ai-terminal).- Verify tự động (self-compare): gaming desktop 1440 + mobile 390 = mọi section CHÊNH 0px; creator đo riêng promo/compare/builds = 0px (số full-page lệch chỉ là artifact đo section dưới chưa settle, đã chứng minh ở AI). 0 tràn ngang, 0 lỗi JS, dark mode sạch. AI terminal gõ đủ 13/13 sau refactor.
CÒN LẠI: editor JS (kéo-thả/sửa chữ trong Gutenberg) + chuyển 3 trang live từ inline sang block. Trang khách hiện VẪN inline clone (chưa đụng); bản block ở ?td_blocks=1.
[1.8.8] - 2026-07-10 (Phase 2-5 AI - trang ai-workstation dựng bằng BLOCK, khớp clone pixel-perfect)
Hoàn tất dựng lại trang ai-workstation bằng block rời, giống clone 100%.
- Block
land-section(mới): 1 section = 1 block,readfilemarkup clone bake nguyên (workload/bench/parts/builds/compare/promo/faq →sections/ai-*.html). Tương tác (accordion FAQ, tab lọc tier, bar benchmark animate, reveal-on-scroll) dùng lại JS clonelanding-ai-workstation.js- cùng selector, chạy đúng. - Subnav dựng từ
navLinkscủaland-hero(CSS + scroll-spy JS tronglanding-enhance.*); navLinks map đúng anchor clone (#workload…#faq). - Trang 104450 post_content =
land-hero+ 7land-section(block rời, kéo-thả được sau khi có editor JS). - Verify tự động (self-compare block ?td_blocks=1 vs clone): mọi section CHÊNH 0px cả desktop 1440 LẪN mobile 390; 0 tràn ngang; 0 lỗi JS; dark mode sạch. Tên/giá build (TD-INFER/ATOM/TRAIN/QUAD/XEON) fetch live từ Woo - block == clone.
- Phát hiện: tên build TD-OTTER… trong HTML tĩnh chỉ là placeholder; JS live thay bằng sản phẩm Woo thật → cả clone lẫn block đều hiện TD-INFER… giống nhau.
- Trang live khách VẪN inline clone (chưa chuyển) - bản block xem ở
?td_blocks=1. Chuyển live + editor JS: bước sau.
CÒN LẠI: editor JS (kéo-thả/sửa chữ), chuyển live AI sang block, và nhân sang gaming + creator (Phase 6).
[1.8.7] - 2026-07-10 (Phase 1 - dựng lại landing bằng block: hero AI workstation faithful + editable)
Bắt đầu dựng lại 3 landing bằng BLOCK RỜI, với ràng buộc: hero + SVG + scene phải GIỐNG clone. Kiến trúc: mỗi section = 1 block; phần visual (hero/terminal/SVG) bake NGUYÊN markup clone vào render, chỉ rút chữ ra thành attribute editable. CSS dùng landing-{slug}.css (scope .tdp-land-{variant}) đã nạp sẵn.
land-herovariantai: viết lại render xuất markup clone y hệt (.hero.ai-hero+ eyebrow + h1.h-display gold + lead + nút primary/link + 3 stat + terminal). Terminal bake vàoterminal-ai.html(13 dòng + 4 GPU meter). Attribute mới:eyebrow,titleHtml(RichText, giữ<span class=gold>+<br>),stats[num/unit/lbl/pct],buttons[label/href/variant primary|link]. Nhánh gaming/creator giữ nguyên (Phase 6).- Nối
landing-enhance.js(gõ ký tự + GPU bar) - block xuất.tdp-land-ai .ai-terminal, tự chạy. Thêm inline-hide script trong render (chống chớp), chỉ ở frontend (bỏ qua editor/REST). - Cờ preview
?td_blocks=1(inc/landing.php): render post_content (block) thay inline clone, để build+đối chiếu mà KHÔNG đụng trang live (khách vẫn thấy inline clone giống 100%). - Set attribute block trang 104450 theo clone. Verify: hero block khớp clone pixel-perfect (eyebrow/headline/lead/nút/3 stat/terminal gõ chữ + màu + bar), 0 lỗi JS. Khác biệt còn lại: thanh subnav (Phase 5 - lắp trang).
CÒN LẠI: workload/benchmark/linh kiện/5 cấu hình/so sánh/promo/faq (Phase 2-4), lắp trang + subnav + tắt inline (Phase 5), nhân sang gaming+creator (Phase 6).
[1.8.6] - 2026-07-10 (AI workstation terminal: gõ TỪNG KÝ TỰ + fix màu + GPU bar chạy %)
Bản 1.8.5 (fade từng dòng) bị sai: landing gốc gõ TỪNG KÝ TỰ có nhịp loading, MÀU chữ sai (mất chữ), và 4 GPU bar không nhảy %. Đối chiếu landing.tandoanh.vn gốc (React): terminal gõ ~1 ký tự/15ms sau ~450ms loading; dòng lệnh sáng rgb(234,240,252).
- FIX MÀU (bug thật): terminal là panel TỐI, nhưng ở light mode token
--ink-*của trang thành màu TỐI (dành cho nền sáng) → dòng lệnht-cmd(dùng--ink-0) ra#1a1510tối trên nền tối = mất chữ. Re-scope--ink-0..3về giá trị dark (chữ sáng) CHỈ trong.ai-terminalkhi light (landing-enhance.css). Sau fix: t-cmd lightrgb(251,248,243). - Gõ từng ký tự (thay fade từng dòng):
landing-enhance.js- ẩn dòng, đọc text, gõ tuần tự từng ký tự (lệnh 11ms, output 4ms, nghỉ 55ms/dòng) sau nhịp loading 450ms; con trỏ.td-term-cursornhấp nháy chạy theo. Xong ~5s (gốc ~4s). Bỏ toàn bộ CSS stagger nth-child của 1.8.5. - 4 GPU meter chạy %: thanh
.ai-meter-bar>divfill 0→đích (transition 1.15s) + số %.ai-meter span:last-childđếm lên easeOutCubic. - Chống chớp: inline script (chỉ variant ai) ẩn dòng terminal NGAY lúc parse (trước paint) → không lóe full text rồi mới gõ. Kích hoạt khi terminal lọt viewport (hero above-fold nên gần như ngay khi load).
prefers-reduced-motion: reduce: hiện đủ text + bar ở đích ngay, không gõ. File enhance KHÔNG sinh tự động (an toàn khi rebuild clone). Verify: gõ char-by-char 0→23→66→169→261, bar 62%→98%, màu sáng cả light/dark, 0 lỗi JS.
[1.8.5] - 2026-07-10 (AI workstation: hero terminal gõ từng dòng như landing gốc)
- Hero landing
ai-workstation: 13 dòng terminal hiện CÙNG LÚC (fade 0.18s) thay vì "gõ" tuần tự như landing gốc. Nguyên nhân: hiệu ứng typewriter là JS runtime của React ở landing gốc, KHÔNG lọt vào clone tĩnh - nên iframe cũ cũng đã không có, không phải regression từ việc inline. - Fix bằng CSS thuần (
assets/css/landing-enhance.css): staggeranimation-delaytrên chính keyframeai-typedsẵn có (0.15s + 0.13s×n) +animation-fill-mode: backwardscho.ai-terminal-line:nth-child()→ dòng ẩn cho tới lượt mới hiện = gõ từng dòng, xong ~1.9s. Không thêm JS, không flash (fill-mode giữ dòng ẩn trước lượt). - File enhancement KHÔNG sinh tự động, enqueue SAU CSS clone (
inc/landing.php) nên rebuildinline_clone.pykhông xoá mất. Scope.tdp-land-ai→ 2 landing kia (không có.ai-terminal-line) không dính. prefers-reduced-motion: reduce→ hiện đủ 13 dòng ngay. Verify: gõ tuần tự 0→2→6→10→13 dòng theo thời gian, reduced-motion 13/13 ngay, pc-gaming/creator-studio 0 lỗi.
[1.8.4] - 2026-07-10 (FAQ sản phẩm: shortcode Flatsome cũ → accordion native)
- 193 sản phẩm (màn hình, tản nhiệt…) có phần FAQ lưu bằng shortcode
[accordion]/[accordion-item]của Flatsome cũ. Theme block không đăng ký shortcode này nên nó hiện literal ([accordion title=…]) trên trang. - Port bộ chuyển đổi từ theme
hungphat-laptop(inc/content-enhance.php): render bằng<details>/<summary>native - accessible, KHÔNG cần JS, nội dung luôn trong DOM (tốt SEO). Prefixtd-accordion, hàmtandoanh_*. - Chuẩn hoá dấu ngoặc cong: nội dung Flatsome lưu
title=”…”(curly) khiếnshortcode_parse_attskhông đọc được attribute → filterthe_contentpriority 9 đổi ngoặc cong → thẳng CHỈ trong cặp[ ], giữ nguyên dấu cong ở body. - CSS trong
single-product.css(+.purged.css), scope PDP vì 193 bài dính đều là product. Màu active dùng--td-brand-strong(đã theme-aware: gold đậm #8a6a00 light / gold sáng #f0c75e dark) nên bỏ được rule override dark mà bản HP phải có. - Verify 5 sản phẩm: 0 shortcode literal, item đầu
auto_opentự mở, tương tác đóng/mở OK, contrast head active 5.07:1 (light) / 12.28:1 (dark) đạt AA, 0 lỗi JS.
[1.8.3] - 2026-07-10 (Logo + backlink Bộ Công Thương ở footer)
- Badge BCT đang hotlink
https://static.tandoanh.vn/wp-content/uploads/2020/02/logoSaleNoti.pngvà trỏ tới bản ghi cũ…/2d6b68ce-…. - Ảnh mới
DaThongBao-BCT.png(360×111) upload vào Thư viện (attachment ID 104715) →/wp-content/uploads/2026/07/DaThongBao-BCT.png; hết phụ thuộc domain ngoài. (Bản đầu 360×135 được thay bằng bản crop sát 360×111: ghi đè file,wp media regenerate 104715để metadata + thumbnail khớp, giữ nguyên URL và attachment ID.) - Backlink đổi sang
http://online.gov.vn/nen-tang/67bfee06-f6fa-4856-943e-48f7b8b6ca8c. Đã mở bằng trình duyệt thật để xác minh (trang là SPA,curlkhông đọc được nội dung): đúngtandoanh.vn- Công ty TNHH TH Hoàng Phương, MST 0313792226. - Cập nhật qua option
tandoanh_business_info(Admin → Thông tin DN → Link nội bộ) và sửa defaultlinks.bcttrong code để option bị xoá cũng không rơi về link cũ. site-footer/render.php:<img>width/height170×64→360×111cho khớp tỉ lệ ảnh thật (3.243) - placeholder aspect-ratio chuẩn, CLS trang chủ mobile 0.0024. Kích thước hiển thị vẫn do CSS (182×56).
[1.8.2] - 2026-07-10 (Hover thẻ thương hiệu trang chủ ra màu xanh link)
- Khối "Thương hiệu uỷ quyền trực tiếp" (
.td-brandwall): rê chuột vào thẻ (INTEL, AMD, ASUS…) thì chữ chuyển xanh link#14529etrên nền gold thay vì màu chữ nhấn - chữ chìm, sai tông. - Nguyên nhân: rule toàn cục
a:hover:not(.td-btn):not(.button):not(.wpcf7-submit):not([class*="__buy"]):not([class*="__cart"]):not([class*="td-pdp-chat"])ởbase.css:55có specificity 0,7,0, đè.td-brand:hover { color: var(--td-on-brand) }(0,2,0) trongtemplates/home.css:320. Đúng lớp lỗi đã gặp ở nút "Mua ngay" (1.6.x) - thẻ nào là<a>mà không nằm trong danh sách:not()đều dính. - Fix: thêm
:not(.td-brand)vào rule toàn cục, sửa cảbase.purged.css. - Verify: hover +
:focus-visible, cả 2 loại thẻ (thường và--star), light + dark ⇒ chữ#1a1505trên nền gold, tương phản 10.82:1 (light) / 11.70:1 (dark), đạt WCAG AA.
[1.8.1] - 2026-07-10 (Số năm kinh nghiệm trang Giới thiệu: hardcode → tự tính)
- Dải số liệu trang
/gioi-thieu/ghi cứng2007(năm thành lập) và17+(năm kinh nghiệm) trongpost_content. Sai - 2026 − 2007 = 19 - và sẽ sai lại mỗi năm. - Thêm
misc.founded_year(mặc định 2007) vào Thông tin DN + ô nhập "Năm thành lập" trong admin. - Helper
tandoanh_founded_year()/tandoanh_years_exp()(dùngwp_date('Y')nên theo timezone site) + 2 shortcode trả số trần, không bọc thẻ:[td_founded],[td_years_exp]- nhét thẳng vào markup có sẵn<span class="tdp-about__num">[td_years_exp]<i>+</i></span>mà không sinh<span>lồng nhau như[td_biz]. post_contenttrang 104669 đổi 2 số cứng thành shortcode. Đổi năm thành lập trong admin là cả hai ô tự cập nhật; sang năm số năm kinh nghiệm tự tăng.
[1.8.0] - 2026-07-10 (3 landing: gỡ iframe, nhúng clone THẲNG vào DOM)
3 landing bespoke (pc-gaming / ai-workstation / creator-studio) đang được nhúng bằng <iframe> trỏ file clone tĩnh landing-clone/{slug}.html (pc-gaming 502KB). Hệ quả: LCP mobile ~3.2s, và nội dung nằm trong document con nên công cụ tìm kiếm không index cho URL trang. Phiên này bỏ iframe nhưng giữ nguyên clone giống tuyệt đối (đúng chỉ đạo cũ) bằng cách nhúng markup + CSS + JS của clone thẳng vào trang.
Cách làm
- Script build bóc mỗi file clone thành 3 phần và scope toàn bộ CSS dưới
.tdp-land-{variant}(:root/html/body→ wrapper;html[data-theme=…] body …→ bỏ tokenbody;@font-face/@keyframesgiữ nguyên;@media/@supportsđệ quy). Script kiểm tra scope xác nhận: 734 / 774 / 823 selector, 0 lọt lưới ⇒ CSS clone không rò ra theme và ngược lại.assets/css/landing-{slug}.css(112-122KB),assets/js/landing-{slug}.js(14KB, defer),inc/landing-inline/{slug}.html(markup).
GOTCHA của bộ scope CSS (đã sập 1 lần, mất light mode)
- Tokenizer phải bỏ qua comment và chuỗi khi quét
{;}. CSS clone có comment chứa dấu chấm phẩy:/* … giữ gold; panel thiết bị vẫn tối */. Quét thô cắt tại;trong comment ⇒ phần còn lại của comment bị coi là selector ⇒ sinh.tdp-land-gaming panel thiết bị vẫn tối */html[data-theme="light"]{…}= selector hỏng, trình duyệt bỏ nguyên rule ⇒ toàn bộ light-mode của landing chết (nền đen giữa site sáng). - Comment đứng ngay trước selector nằm chung prelude → phải tách ra rồi mới scope, không thì scope bị nhét vào giữa comment.
- Script verify phải dùng CHÍNH tokenizer đó. Bản verify đầu tiên quét thô nên báo "0 lọt" trong khi CSS đang hỏng - kiểm tra vô giá trị. Verify giờ thêm điều kiện: scope không được xuất hiện trong comment.
inc/landing.php: filterthe_contentđổ markup vào<div class="tdp-land-inline tdp-land-{variant}">+ enqueue CSS/JS theo slug. Sub-nav sticky.td-subnavdựng từ nav clone (nav gốcdisplay:none), giờ đọc thẳng cùng document thay vìcontentWindow. Thêmscroll-margin-top:120pxcho[id]để header sticky của site không che đầu section.- JS clone vốn đã có nhánh
inFrame = window.parent !== window⇒ chạy standalone tự cuộn, không cần sửa.
Kết quả đo (mobile, CPU 4×, Slow 4G, sau WPFC cache)
| Trang | LCP trước (iframe) | LCP sau (inline) | CLS |
|---|---|---|---|
| pc-gaming | 3168ms | 1232ms | 0.033 |
| ai-workstation | - | 1952ms | 0.004 |
| creator-studio | - | 1248ms | 0.037 |
- Đối chiếu pixel với clone standalone:
#buildscao 1188px ở cả hai, tổng chiều cao pc-gaming 7429px ở cả hai ⇒ khớp hình học tuyệt đối. Tab lọc, ảnh SVG trong card, TD-EAGLE, giá live (RESTtandoanh/v1/prices) đều còn nguyên. - QA 3 trang × {mobile 390px, desktop 1440px} × {light, dark}: 0 tràn ngang, 0 lỗi JS, 0 request ≥400.
Ghi chú
- Bộ block
tandoanh/land-*vẫn còn trongpost_contentvà trong theme (bịthe_contentche). Trong lúc điều tra đã sửa 3 lỗi của bản block-native (thiếu enqueuelanding-motion.js;landing-scene-gaming.csschưa bao giờ được nạp nên 4 thẻ HUD hero rơi thành text; kill-switch.td-gaming-card{display:none}) - giữ lại phòng khi cần bản editable. landing-clone/là nguồn: sửa clone rồi chạy lạiinline_clone.py, đừng sửa tay file sinh ra.
Khác
- Footer: thêm liên kết Giới thiệu (
/gioi-thieu/) đầu cột "Hỗ trợ mua hàng", có ô nhập URL trong admin → Thông tin DN → Link nội bộ. - Admin Mega Menu: 3 nút hành động cao lệch nhau (nút Lưu có
button-hero) và chữ nút Lưu bị.hplt-admin .button { color: var(--hplt-ink) }đè thành mực tối trên nền gradient xanh (2.3:1). Fix: đồng bộ 44px,color:#fff !importantcho.button-primary⇒ 5.27:1 đạt AA. - Admin Trả góp: nút icon Chọn logo / Gỡ 30px → 40px, bằng chiều cao ô nhập cùng hàng (luật 40px toàn admin). Audit script 13 trang admin: 0 vấn đề.
[1.7.9] - 2026-07-10 (Audit Security + Performance toàn theme - 6 vùng, 6 agent)
Audit toàn diện theme (183 file PHP / 23k dòng + 134 JS) qua 6 agent song song (4 security: authz/SQLi/XSS-file-SSRF/secrets-CSRF-money; 2 perf: DB-query/asset), mỗi finding tự kiểm chứng bằng wp eval/đo query. Kỷ luật code nền tốt: không có lỗ hổng critical/high - nonce+capability đủ mọi AJAX/admin-post, SQL toàn prepare/ép-int, không secret hardcode, không tin giá client. Các fix đã áp:
Performance
- [LỚN NHẤT] Tab Hiệu năng PDP (VGA/CPU) ~397 query / ~1s mỗi render, KHÔNG cache (
inc/perf/perf-data.php):td_bench_chip_value(2 query/lần, uncached) gọi trong vòng lặp lồngforeach metric × foreach 16 card cùng dòng. Mỗi lần save 1 product → WPFC purge → mọi trang VGA/CPU rebuild ở mức này. Fix: cache 5 hàm thuần-theo-chip (gaming_matrix/ai_matrix/cpu_matrix/gaming_self/self_groups) vào object cache grouptd_perfTTL 12h. Admin lưu benchmark gọiwp_cache_flush()(tandoanh-benchmarks/admin-page.php:72) nên cache tự sạch - không lo hiển thị số cũ. Đo thật: 397 q/1035ms → 0 q/2ms khi warm (giảm 100%), output cold==warm khớp tuyệt đối, invalidation verify đúng. SHOW TABLESchạy mỗi request (inc/woo/checkout-extras.php:157, hookinitprio 1): bảng promo tồn tại vĩnh viễn nhưng vẫnSHOW TABLES LIKEmỗi request. Fix: option flag autoloadtd_promo_table_ready, return sớm ⇒ −1 query/request.- Tra cứu MST (
td_lookup_tax_code) gọi HTTPapi.xinvoice.vnmỗi lần khách gõ, không cache (inc/woo/checkout.php): thêm transient theo MST 12h (MST không tồn tại đệm 10 phút) - cắt outbound lặp + chống lạm dụng endpoint nopriv.
Security
- [CONFIRMED, medium] CSV Injection (
inc/woo/checkout-extras.phpexport promo subscribers): khách vãng lai (nopriv) nhậpbilling_first_name==HYPERLINK(...)/=cmd|'/c calc'!A1→ lưu DB → admin Export CSV mở Excel/LibreOffice thực thi công thức.sanitize_text_fieldKHÔNG lọc= + - @. Fix: prefix'cho mọi ô bắt đầu bằng= + - @ \t \rtrướcfputcsv(test 6/6 payload). - PDP "sản phẩm vừa xem" JSON in thẳng
<script>(inc/woo/pdp.php): tên SP chứa</script>(shop manager nhập) có thể phá block. Fix:wp_json_encode(..., JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT)(in-depth). - Object injection phòng thủ (
inc/blocks/registry/buildband/render.php):maybe_unserialize($raw, ['allowed_classes'=>false])cho dữ liệu session builder. - Bản dịch AI title lưu raw (
inc/i18n/ai-translate.php):wp_strip_all_tagscho_td_en_titletrước khi lưu (title in quathe_title, phòng AI provider trả HTML). esc_likethiếu (inc/woo/checkout-extras.php:251search subscriber): người dùng gõ%/_thành wildcard (chức năng, không SQLi vì đãprepare). Fix$wpdb->esc_like.
Fix nút Chat Facebook/Zalo PDP hover khó nhìn
- 2 lỗi chồng nhau: (1) nền hover xanh FB gốc
#1877f2+ chữ trắng chỉ 4.23 (dưới AA); (2) NẶNG hơn - chữ hover KHÔNG phải trắng mà thành xanh link--td-link-hover(chữ xanh trên nền xanh, contrast 2.24 gần trùng màu) vì globala:hover:not(.td-btn)...(specificity 0,6,1) đècolor:#fffcủa.td-pdp-chat__fb:hover(0,2,0) - nút chat là<a>không nằm trong danh sách loại trừ (đúng lỗi cũ tái diễn). - Fix: (a) nền hover FB
#1877f2→#1465d8(trắng 5.41), Zalo#0068ff→#0059dd(6.05); (b) thêm:not([class*="td-pdp-chat"])vào global a:hover (base.css + base.purged.css); (c) thêm[data-theme="dark"] .td-pdp-chat__fb:hover/__zalo:hover{color:#fff}vì dark default (chữ xanh nhạt) đứng sau đè color hover. Verify Playwright 4 trạng thái (light/dark × default/hover) đều chữ đạt AA: default 5.41/7.2, hover 5.41 cả 2 mode.
Ghi nhận (KHÔNG phải lỗi - đã kiểm chứng)
mix-blend-mode: multiplyởpage-tu-chon-cau-hinh-pc.css:608là dead CSS (false positive của asset audit): 2 block sau cùng selector overridemix-blend-mode:normal+img{display:none}(thay bằng::beforemask SVG) → multiply KHÔNG active, không repaint.seasonal.css(60KB) nạp cả 8 preset site-wide khi bật mùa (~13KB gzip thừa/trang): finding asset lớn nhất còn lại, NHƯNG preset đang TẮT nên tác động hiện tại = 0 (file không enqueue). Tách per-preset là refactor lớn đụng cơ chế scene data-URI - chờ duyệt trước khi làm.- Điểm LOW không sửa (by-design/bounded): REST
/qnapublic (honeypot+rate-limit+hold), SSRF i18n endpoint/buyback URL (admin/editor-only), cookietd_cart_countthiếu HttpOnly (chỉ số đếm giỏ), autoload 682KB do core+plugin khác (option theme đều autoload=off cho cái to).
[1.7.8] - 2026-07-09 (Seasonal v4 - redesign theo taste skill)
Giao diện
- Seasonal v4 - redesign toàn bộ decor theo mùa: đổi từ ngôn ngữ clip-art nhiều màu sang line-art 1 tông + hairline tiết chế:
- Background 2 bên: mỗi mùa 1 tile line-art dọc kiểu engraving (stroke 1.6-1.7, đơn sắc
--td-season-line+ accent rất hạn chế) + 2 lớp orb radial-gradient mờ tạo chiều sâu + mask-image fade mờ dần vào giữa trang; bên phải soi gương. Opacity .5 light / .32 dark. - Khung card: bỏ sọc kẹo/ngoặc dày/viền kép - khu mặc định = hairline 2px ở đỉnh fade 2 đầu (chừa mép 14%), khu TOP + section lẻ home = corner tick 2 nét mảnh (trên-trái đậm, dưới-phải 55%), khu shop/section chẵn = hairline ĐÁY; nền card chỉ wash 3.5% ở đỉnh, motif góc ảnh vẽ lại line-art mono 21px op .55 (watermark, hết kiểu sticker).
- Ornament cạnh LOGO: vector line-art 26px sát phải logo từng mùa, tông SÁNG cho header nền ink (mai vàng+nhị đỏ / thông+sao / sao vàng / mặt trời / bông tuyết / bí ngô / đèn lồng+trăng / mũ tốt nghiệp) - ẩn <640px.
- Hiệu ứng rơi: giảm 26→16 hạt (mobile 9), rơi chậm 12-22s, hạt nhỏ 5-7px; depth: 1/3 số hạt blur 1.2px + mờ + nhỏ, 1/4 rõ hơn; quỹ đạo cong nhẹ (keyframe 3 mốc); bỏ hết clip-path lòe loẹt (dơi to/máy bay/sao 10 cánh) - thay bằng cánh hoa nhỏ/tuyết mềm/đốm sáng vàng ấm/bụi nắng/lá thu trầm/confetti giấy 2 tông nhạt.
- Background 2 bên: mỗi mùa 1 tile line-art dọc kiểu engraving (stroke 1.6-1.7, đơn sắc
- Trang admin Seasonal redesign: tab menu đổi tiếng Anh "Seasonal" (đồng bộ policy menu EN), H1 "Seasonal - Giao diện theo mùa"; grid chọn mùa CỐ ĐỊNH 3 cột; card kiểu double-bezel (shell ngoài + ảnh sample lồng trong, bo concentric), radio ẩn thay bằng ring xanh + chip, hover nâng nhẹ + shadow khuếch tán, nút "Xem thử ngoài web" thành pill có icon tròn (hover icon trượt chéo), transition cubic-bezier(.32,.72,0,1). 8 ảnh sample chụp lại theo art v4.
- Verify sau redesign: 8/8 preset strip + motif + hairline OK (Playwright, inject client-side), admin render đúng EN + 3 cột + bezel.
Seasonal v14 - chuẩn hoá contrast theo PSI/WCAG AA
- NGUYÊN TẮC MÀU TOÀN HỆ (theme gốc + 8 mùa): nền SÁNG → chữ TỐI, nền TỐI → chữ SÁNG; tỉ lệ contrast đạt WCAG AA (text ≥4.5, text lớn/UI ≥3.0 - đúng thước đo Lighthouse/PSI Accessibility) NHƯNG chỉ chỉnh độ đậm/nhạt trong cùng tông, không đổi hue premium.
- Fix "chữ tối thui" (mùa Hè): Hè là mùa DUY NHẤT light dùng chữ tối (#241200 trên cam #d96407) - tái hiện được trên đường khách thật (không phải do cache). Fix: cam đậm thêm 1 nấc
#c2410c(hover/strong#a83c05) để dùng chữ kem #fff3e6 như 7 mùa kia - đo thật light 4.74; dark Hè khoá lại--td-on-brand:#241200(nền cam sáng → chữ tối, đúng nguyên tắc; trước đó kế thừa kem từ light mới sẽ hỏng). - BÀI HỌC QA: test decor/màu PHẢI đi đường khách thật (server bật preset + WPFC bundle + purged CSS swap của speed.php), KHÔNG inject CSS thủ công - inject đã che mất lỗi này nhiều vòng.
- Audit axe-core (đúng engine PSI a11y) 90 runs (5 trang × 9 trạng thái × light/dark): 160 instance → 8 cụm lỗi gốc, fix TOÀN BỘ:
- Token mới
--td-brand-bright(tokens.css :root + 8 preset): accent TEXT trên nền tối CỐ ĐỊNH (footer #1e1e23, đầu cột bestsellers/topbar #15151a) - light preset brand đậm (đỏ cờ #ad1a14 chỉ 2.31) chìm trên nền tối; giá trị = brand của DARK preset (5.18-11.3). Áp vào:.footer-hours__head,.footer-col__title(viền),.footer-contact svg,.topbar a:hover(layout.css + purged), link "Xem tất cả".td-tb__head a(top-row.php). - BuildPC pill/btab active bị specificity đè (root cause "GAMING · 28M" 2.04-2.68):
html[data-theme="light"] .td-bp__pill(0,2,1) THẮNG.td-bp__pill.is-active(0,2,0) → chữ active kẹt ink .72 trộn trên nền brand mùa. Fix home.css + purged: thêm override light.is-active{color:var(--td-on-brand)}(4.74-10.82),.is-active .m{opacity:1}(hết rớt 4.45 quoc-khanh dark), btab active light =color-mix(strong 72%, #1a1510)(6.03-9.52; strong thuần gốc gold chỉ 4.12),.swap:hover#16130a → var(--td-on-brand). - Giá gạch carousel bestsellers dark 3.74 (lỗi duy nhất của THEME GỐC): legacy wp_extra
del{opacity:.8}- épopacity:1!importanttheo đúng pattern woo-card 0.9.6 (dark 5.07 / light 4.97). - Noel
--td-brand-strong#1e7a46 → #1b6f3e (brand pill sao/hotline trên nền hồng mix 4.46 → 5.17). - Hè
--td-info#0bb5c4 → #077e89 light (badge "Chính hãng" chữ trắng 2.49 → 4.82); dark Hè trả lại teal sáng #0bb5c4 vì badge dark chữ navy (5.9). - Link popup "vừa mua" (woo-notifications) inline #8a6a00 cố định → override
var(--td-brand-strong)!importanttrong plugin-overrides.css: đổi theo mùa + ≥5.07 trên trắng mọi preset (mùa Đông hết bị gold chìm 2.27); timestamp<small>inline #94a3b8 (2.56) → #54545f light / #a6a6b0 dark.
- Token mới
- GOTCHA wptexturize phá onclick inline (Lighthouse PDP 97→100):
onclick="...window.location='...'..."trong content-single-product.php bị wptexturize đổi nháy đơn thành’trong HTML cache → attribute không đóng, browser nuốt<svg aria-hidden="true">vào<a>= lỗi aria-hidden-focus. Fix: bỏ onclick inline →data-td-msapp+ delegated click handler trong theme.js (deep-link Messenger mobile/iPad giữ nguyên hành vi). LUẬT: cấm onclick inline chứa quote trong template - texturize/cache sẽ phá. - Lighthouse Accessibility sau fix (đường khách thật, server preset tet): home 100, /shop/ 100, PDP 100 (trước 97); color-contrast audit = pass, 0 items cả 3 trang.
Seasonal v14 - QA + Audit vòng 2 - thêm 3 lỗi thật ngoài contrast
- Nút "Build PC Custom" (.meganav-build) chìm trên trang Build PC / dark (contrast 1.37 gốc, 1.54-2.72 mọi mùa): page-tu-chon-cau-hinh-pc.css có rule
[data-theme="dark"] .meganav-inner > a { color: var(--td-text)!important }quét CẢ nút gradient gold/mùa → chữ sáng trên nền sáng. Fix::not(.meganav-build)(cả bản .css + .purged) → nút trả về chữ --td-on-brand tối đúng mọi mùa (đo lại 5 mùa dark: chữ tối trên nền sáng). Đây là nút header giống mọi trang nhưng CHỈ trang builder có rule đè này → home/shop/pdp không dính. - Bảng giá thu mua thiếu keyboard focus (axe full-ruleset, serious, dính 9 preset × 2 theme):
.tdp-buyback__pricescrollvùng cuộn ngang không nhận focus bàn phím. Fix:tabindex="0" role="region" aria-label(buyback-pricelist.php) +:focus-visibleoutline gold,:focus:not(:focus-visible)bỏ outline chuột (page-thu-mua-hang-cu.css). - Heading nhảy cấp H1→H3 trang thu mua (Lighthouse heading-order): block
prem-stepshardcode<h3>; khối "quy trình" hero đứng ngay sau H1 → nhảy cấp. Fix: thêm attributeheadingLevel(2-4, mặc định 3) cho block + render động; set khối hero = h2 trong content page 62102 (khối "Quy trình" giữa trang giữ h3 vì có h2 cha). LUẬT: block có tiêu đề phải cho chỉnh cấp heading, không hardcode. - Audit toàn diện vòng 2 (2 agent + script riêng): (a) axe FULL ruleset WCAG 2.1 A/AA 108 lượt (6 trang × 9 preset × 2 theme, bỏ color-contrast đã pass) → chỉ 1 lỗi (pricescroll, đã fix); Home/Shop/PDP/BuildPC/Cart sạch tuyệt đối. (b) Script đo contrast MỌI nút (23 selector × 6 trang × 9 preset × 2 theme = 1260 phép đo, tính cả nền gradient axe bỏ qua) → sau fix 0 lỗi. (c) Lighthouse Accessibility 5 trang chính = 100/100 (builder, thu-mua đều 100 sau fix).
- Audit verify vòng 2 (90 runs lại sau fix): 160 → 0 vi phạm CSS theme. Tồn duy nhất = khung hình popup "vừa mua" đang fade-in (mid-opacity mọi text đều loãng - transient, Lighthouse thực tế không bắt trúng); spot-check computed style live xác nhận footer/tb-head = brand-bright, pill/btab active đúng on-brand/mix, del opacity 1,
.mopacity 1 (phải thêm override light.is-active .mvìhtml[light] .td-bp__pill .m{opacity:.92}là (0,3,1) thắng (0,3,0)).
Seasonal v13 - NÚT CTA đổi màu theo mùa
- Root cause: 4 nhóm nút CTA gold (
.td-btn--primarybase.css, nút Build PC Custom + nút gọi drawer megamenu.css,.td-bp__btn--goldhome.css - kèm bản .purged) HARDCODElinear-gradient(#ffe58f,#e3c56e,#b2933a)đè lênvar(--td-brand), trong khicolor: var(--td-on-brand)LẠI đổi theo preset → bật mùa: nền kẹt gold, chữ đổi thành kem/navy của mùa = vừa "không đổi màu" vừa "lỗi light/dark". - Fix: biến hoá toàn bộ - tokens.css thêm
--td-cta-grad/--td-cta-grad-hover/--td-cta-shadow-c(mặc định = đúng gradient + shadow gold cũ, ngày thường giữ nguyên từng byte); rule chung[data-preset]{ --td-cta-grad: linear-gradient(135deg, color-mix(brand 62% trắng), brand 50%, brand-strong); hover tương tự sáng hơn; shadow-c: brand }→ bật mùa là nút tự đổi CẢ nền + hover + bóng, chữ --td-on-brand của preset khớp nền (AA on-brand vs brand đã check 16/16 từ trước). Sửa 6 file CSS (3 gốc + 3 purged) bằng script thay đúng chuỗi; shadowrgba(227,197,110,.x)→color-mix(var(--td-cta-shadow-c) x%, transparent). - Verify đo computed: mặc định giữ gold; tet/noel/dong × light/dark nút đổi đúng màu mùa, contrast chữ vs nấc giữa gradient 4.9-9.5.
- QA agent 63 combo (3 trang × [mặc định + 8 mùa] × light/dark @1600 + home mobile 390): nút CTA biến mới PASS 100% (0 stop gold khi bật mùa, contrast ≥4.5 mọi preset, hover + shadow đổi đúng, mặc định giữ gold nguyên trạng); quét goldLeftovers toàn trang = RỖNG (12 nhóm gold mặc định đều tự đổi khi bật mùa); 0 lỗi JS, 0 tràn ngang kể cả 390px. 1 finding thật đã fix: 2 nút nav "Danh mục sản phẩm" (.td-mega__toggle) + "Build PC Custom" (.meganav-build, layout.css) dùng gradient brand→brand-hover nhưng 8 block dark preset THIẾU override
--td-brand-hover→ stop cuối gradient dark lẫn màu light, contrast rớt 2.05-3.01 → bổ sung --td-brand-hover cho cả 8 dark preset (AA on-brand vs hover pass 8/8), re-verify 4 mùa tệ nhất: 6.71-9.01.
Seasonal v12 - BỘ VECTOR CHÍNH THỨC (thay ảnh GPT)
- Nguồn: 2 gói "Seasonal vector illustrations" - 8 mùa × 2 hình TRÁI/PHẢI riêng (300×900, nền trong suốt, có cả SVG + PNG; dùng SVG cho nét + nhẹ). Deploy 16 file
assets/img/seasonal/scene-{preset}-{left|right}.svg(map tên: quockhanh→quoc-khanh, trungthu→trung-thu, tuutruong→tuu-truong); xoá 8 PNG gen GPT. - Cơ chế inline override nâng cấp trái/phải: ::before dùng -left.svg, ::after dùng -right.svg +
transform:none(BỎ scaleX(-1) - hình phải được vẽ riêng, không soi gương nữa); neocenter 164px= phần tử "treo dây" trong hình bắt đầu ngay dưới khối header đục, trông như treo từ header; sizemin(258px,92%) auto; opacity 1 (dark .9); orb + chấm hạt giữ nhẹ (8%/7%/32%). - 2 bug trong lúc triển khai (tự bắt + fix): (1) dùng
sprintftrên chuỗi CSS chứa%→ PHP 8 ValueError "Unknown format specifier" làm frontend 500 - đổi sang str_replace placeholder{SCENE}; (2) sửa xong file mà fatal vẫn còn - opcache php-fpm giữ bản cũ, phảisystemctl reload php8.2-fpm(gotcha cũ của prod lặp lại trên staging). Verify sau fix: home 200, inline in đúng left/right + transform:none ×8 mùa, screenshot 2 bên khác nhau đúng thiết kế. Sample admin chụp lại theo bộ vector. GOTCHA quy trình: mọi lần sửa seasonal.php nghi opcache → reload php8.2-fpm trước khi debug tiếp.
Seasonal v11 - 8 SCENE ẢNH AI HOÀN CHỈNH
- Tạo ảnh scene mùa bằng dịch vụ AI tạo ảnh (kích thước 1024x1536, chất lượng cao). GOTCHA: dịch vụ KHÔNG hỗ trợ
background:transparent→ gen trên nền magenta thuần #FF00FF rồi chroma-key ImageMagick (-fuzz 18% -transparent + alpha Erode Diamond:1 + -trim + -resize 760x). - Vòng 1 màu bị mờ, không vivid (prompt ghi "muted palette") → vòng 2 đổi prompt "premium glossy 3D render, VIVID rich saturated colors, sparkling highlights" + inline override cho ảnh AI hiện
opacity:1(dark .88) - kết quả photorealistic rực rỡ: Noel cây thông châu bóng loáng + 6 hộp quà nơ satin; Tết mai vàng bonsai treo đồng xu tua đỏ + chậu sơn mài + đào hồng + lì xì/quýt/pháo chuỗi; đủ 8 mùa deploy vàoassets/img/seasonal/scene-*.png(cơ chế tự nhận của v10). Sample admin chụp lại theo ảnh AI.
Seasonal v10 - đường ống ẢNH AI
- SVG code tay đã tới trần chất lượng → chuyển hướng ảnh AI render thật. Server không tự gen được (key Gemini của buildpc đã hết hạn/invalid, key PSI bị chặn generativelanguage API) nên dựng sẵn đường ống: theme tự phát hiện file
assets/img/seasonal/scene-{preset}.png(nền trong suốt, ảnh dọc) và inline-CSS đè scene SVG của mùa đó (giữ orb + chấm hạt, size min(240px,88%), ver theo filemtime) - thả ảnh vào là chạy, xoá ảnh là quay về SVG, không đụng code. Smoke test: tạo file giả → inline override sinh đúng → đã xoá. - Bộ prompt gen ảnh chuẩn 8 mùa (kèm yêu cầu chung: portrait 2:3, soft 3D clay render, palette trầm, nền trong suốt/magenta để chroma-key).
Seasonal v9.1
- Scene neo CHÍNH GIỮA DỌC màn hình (
background-position: center centerlayer scene): neo theo px từ đỉnh kiểu gì cũng bị khối header đục (~160px: topbar+logo+nav) che mất đầu (đã dính 2 lần: cây thông rồi lá cờ) - center thì scene luôn trọn vẹn ở mọi chiều cao màn hình. Verify chụp noel + quốc khánh @1000px cao: sao/ngọn thông/chóp cờ nguyên vẹn. - Vẽ lại hero Noel lần 2: bản hero "tán organic răng cưa" render LỖI path (tán rời rạc, hở thân - path zigzag tự cắt) → dựng lại theo cấu trúc 4 tầng tam giác tin cậy (đã render chuẩn ở v8), phóng to + tuyết mép tầng + 13 bóng đèn halo + 4 hộp quà gốc. BÀI HỌC: path SVG phức tạp tự vẽ tay phải render-test trước khi giao - cấu trúc hình học đơn giản chồng lớp an toàn hơn path liền ngoằn ngoèo.
Seasonal v9
- Strip 2 bên đổi kiến trúc: scene KHÔNG LẶP - layer scene chuyển repeat-y → no-repeat (strip là fixed nên 1 cụm chính luôn nằm trong tầm mắt; lặp dọc sinh 2-3 cây thông trùng nhau). Bên dưới scene thay bằng layer 4 mới: chấm hạt mờ màu mùa (radial dots 34×42 repeat, color-mix 40% var --td-season-line) phủ toàn dải cho khỏi trống. Scene neo
center 120px(né header đục). - Cây Noel vẽ lại thành 1 CÂY TO "siêu thật": tán organic răng cưa liền khối (không còn 4 tam giác rời) 2 lớp sáng/tối, tuyết đọng theo mép cành từng vệt zigzag, sao ngọn glow 2 lớp + tia sáng, 5 dây đèn với ~20 bóng, mỗi bóng có quầng sáng (halo radial) riêng xen kẽ đỏ/vàng/xanh specular, thân gỗ gradient, 4 hộp quà chất gốc trên đồi tuyết + bóng đổ.
- Fix bug góc border khung mùa gãy: ruy băng/tick vẽ sát mép (0,0) bị border-radius 14px của card clip cong thành vệt gãy → ruy băng khung A/C thụt 16px 2 đầu + bo đầu thanh (3px), tick khung B thụt vào (10px,10px) kiểu crop-mark - không nét nào chạm góc bo nữa. Verify chụp cận card /shop/: góc sạch.
- Xác nhận: mọi khu list đều có decor - motif mùa trên từng card + ornament cạnh tiêu đề khu + ruy băng/tick theo khu.
Seasonal v8
- Background 2 bên chuyển từ vật thể rải rác sang SCENE LỚN có bố cục (giữ chất 3D v7): Noel = cây thông to 4 tầng tuyết phủ + sao glow ngọn + 3 dây đèn vàng uốn quanh + 8 châu treo (đỏ/vàng/xanh specular) + 4 hộp quà chất dưới gốc trên đồi tuyết; Tết = chậu mai lớn nở rộ (mai vàng + nhánh đào hồng đan xen) + lì xì/quýt/pháo dưới gốc + sao rơi từ tán; Đông = người tuyết TO (mũ len + khăn đỏ + tay cành cây) đứng cạnh thông tuyết trên đồi; Trung thu = trăng rằm to + ĐÔI thỏ ngồi dưới trăng + 2 đèn lồng treo 2 bên + đèn ông sao + bánh trung thu hoa văn; Halloween = cụm 3 bí ngô to-nhỏ (quả to khắc mặt ĐỘI mũ phù thuỷ) + trăng + 2 bầy dơi + nhện thả tơ; Quốc khánh = cột cờ lớn + cờ sao vàng bay + chùm bóng bay đỏ-vàng có dây + pháo hoa + bồ câu; Hè = bãi biển (biển sóng + dải cát) với dừa nghiêng + phao + bóng chuyền + xô cát; Tựu trường = BẢNG PHẤN TO TRÊN GIÁ 3 CHÂN + cặp sách dựa nghiêng vào chân giá + chồng sách + táo đỏ + bút chì. Mỗi tile: scene chính ~60% + khoảng nghỉ thưa (kẹo gậy/bông tuyết/sao/sóng) để lặp dọc tự nhiên. Sample admin chụp lại.
- Fix cây thông bị "cắt ngang thân": header nền đục (~100px) đè lên strip z-index:-1 → scene đầu tile bị che ngọn. Fix dịch pha layer tile
background-positioncenter top → center 120px - vùng bị header che giờ chỉ dính phần đệm thưa cuối tile, scene chính hiện nguyên vẹn dưới header. Verify lại 8 mùa (noel/tet/dong/halloween/quoc-khanh duyệt mắt, còn lại cùng công thức): không còn vật thể chính nào bị cắt.
Seasonal v7
- Nâng toàn bộ 8 tile + 8 motif từ flat lên DIMENSIONAL/3D bằng radial/linear gradient trong SVG defs: cánh mai/đào gradient sáng tâm→đậm rìa + nhị chấm phấn hoa; thông 2 lớp tán (mặt sáng) + tuyết gradient; hộp quà highlight dọc + ruy băng ánh kim + bóng đổ ellipse dưới mọi vật thể; châu Noel/khối cầu có specular highlight; người tuyết 3 khối cầu radial + mũ len; trăng glow 2 lớp + crater; đèn lồng phát sáng từ trong + tua rua hạt; bí ngô múi gân tối + mảng sáng; mũ phù thuỷ khối; cờ vải gợn nếp (3 vệt bóng dọc); cặp sách da 2 lớp nắp + khoá kim loại radial + chỉ may; bảng phấn khung gỗ có vân; dừa gân tán + vân thân; phao 3D; bút chì tẩy + đai kim loại. Palette giữ tông trầm v6. Sample admin chụp lại theo v7.
Seasonal v5
- Cân bằng lại độ hiện diện, giữ ngôn ngữ line-art (không quay lại clip-art): card viền tông mùa rõ hơn (mix 42%), ruy băng 3px gradient MƯỢT 2 tông mùa (line→accent, không sọc pattern) đỉnh khu A / đáy khu C; khu B tick góc đậm 2 tông + hairline mờ nối; motif góc ảnh phóng 27px op .72; ornament mùa ngay cạnh TIÊU ĐỀ từng khu list (
.td-shead__row::after= mask var--td-season-motif+ màu--td-season-line, dark tự pha sáng); strips 2 bên đậm hơn (opacity .62/.4) + thêm lớp chấm pattern màu mùa (radial dots 30×38) cho đầy; fx 22 hạt desktop / 12 mobile. Refactor: motif 8 mùa chuyển thành CSS var--td-season-motifdùng chung 3 nơi (card + tiêu đề + sẵn cho nơi khác). - Fix bug admin chọn mùa hiện 2 lựa chọn: trạng thái chọn trước đây bám cả class server-render
.is-active(card của option đã lưu) LẪN:has(input:checked)(card đang bấm) → nhìn như chọn 2 mùa. Bỏ hẳn class, chỉ còn:has(input:checked)- bấm mùa khác là card cũ nhả ring ngay. Sample admin chụp lại theo art v5.
Seasonal v6
- Đổi từ line-art đơn sắc sang MINH HOẠ FLAT MÀU THẬT, palette trầm (không neon): mỗi mùa vẽ lại đủ vật thể biểu tượng - Tết: cành mai VÀNG + cành đào HỒNG + lì xì đỏ sao vàng + pháo + đồng tiền; Noel: cây thông XANH tuyết phủ sao vàng + hộp quà đỏ nơ vàng + hộp quà xanh + kẹo gậy + châu đỏ + người tuyết mây; Quốc khánh: cờ đỏ sao vàng bay + pháo hoa + chim bồ câu; Hè: mặt trời + cây dừa + phao sọc đỏ-trắng + sóng + sao biển; Đông: NGƯỜI TUYẾT đội mũ khăn đỏ cà rốt + thông tuyết + bông tuyết to + đụn tuyết; Halloween: bí ngô mặt cười cuống xanh + mũ phù thuỷ tím sao + trăng vàng + dơi + kẹo xoắn; Trung thu: trăng vàng crater + THỎ trắng + đèn lồng đỏ tua vàng + đèn ông sao + mây; Tựu trường: BẢNG PHẤN xanh khung gỗ (chữ A + vạch phấn - chữ đối xứng vì strip phải soi gương scaleX(-1), "ABC" từng bị lật ngược) + CẶP SÁCH đỏ khoá vàng + chồng sách 3 màu + bút chì + mũ tốt nghiệp.
- Motif card + ornament tiêu đề + charm logo cùng đổi sang minh hoạ màu (var
--td-season-motifdùng chung 3 chỗ; charm logo bỏ mask, dùng thẳng motif màu mid-tone + drop-shadow nhẹ - đọc được cả header trắng lẫn ink). Motif card 28px op .9. Strip opacity .8 light / .5 dark (bỏ lớp chấm - minh hoạ màu tự đầy đặn); fx Tết rơi 2 loại cánh mai vàng + đào hồng xen kẽ. Sample admin chụp lại theo v6. - PASS: 32 combo frontend (8 preset × home/shop × light/dark @1920) - strip 3 lớp + mask fade + width 290 đúng, hairline/tick theo khu, motif op .55, fx 16 hạt + depth blur, 0 tràn, 0 lỗi JS; 1366/390 strip ẩn đúng; admin Seasonal: menu EN, grid 3→2→1 cột đúng breakpoint (1600/1280/800), 9 card + 8 sample load thật, flow "Xem thử ngoài web" (?td_preview_preset=noel) áp data-preset + nạp CSS đúng chỉ cho admin; trang Build PC hết PHP Warning.
- 2 finding thật về ornament logo → ĐÃ FIX cùng ngày: (1) ornament đặt cạnh phải logo đè ô search 14-22px (khe logo→search chỉ ~12px) → chuyển thành charm đậu góc trên-phải logo (right:-6/top:-9, 21px, xoay 8°); (2) tông sáng chìm trên header light (nền TRẮNG chứ không phải ink - contrast 1.4-2.2:1) → đổi kiến trúc: hình = CSS mask, màu = background-color bám
--td-season-line(light dùng tông đậm ≥3:1, dark tự pha sángcolor-mix(... 45%, #fff)) - 1 URI/mùa dùng cho cả 2 mode. Verify lại: mask áp đúng, không đè search, nhìn rõ cả light lẫn dark.
[1.7.7] - 2026-07-08 (Benchmark dựng phim + đồng bộ màu admin)
Mới
- Drawer mobile ăn config Mega Menu: mobile-nav.php thêm dispatcher như desktop - ưu tiên option
tandoanh_megamenu_config(map tops/groups/links → drill-down: group không tiêu đề đổ link thẳng panel cấp 1, group có tiêu đề + links thành panel cấp 2, group không links thành row link), chưa lưu config thì fallback menu nguồn như cũ. Verify: nhánh config với seed editor ra HTML giống từng byte nhánh nav (root + 32 panel). Transient drawer đổi keytandoanh_mnav_v3; trang Mega Menu lưu/reset config đều bust drawer. Từ giờ sửa config là đổi CẢ desktop lẫn mobile - config là nguồn duy nhất. - Giao diện theo mùa v3 (spec "làm kỹ thêm" trong ngày) - (1) Ruy băng card đổi thành hoạ tiết riêng từng mùa qua var
--td-season-ribbon(Tết sọc đỏ-vàng chéo, Noel kẹo gậy đỏ-trắng-xanh, Quốc khánh đỏ-vàng-đỏ, Hè cam-teal, Đông xanh băng, Halloween cam-đen, Trung thu đỏ-vàng, Tựu trường xanh-vàng), dùng chung khung A (đỉnh) + khung C (đáy); card thêm glow toả từ đỉnh (radial color-mix 9%); ngoặc góc khung B nâng 2 nấc + chấm son 2 góc. (2) 8 tile background 2 bên VẼ LẠI chi tiết nhiều lớp (fill-opacity depth): Tết = cành mai 2 tầng hoa + nụ + lì xì sao vàng + đồng xu mờ + cánh đào; Noel = thông phủ tuyết + sao ngọn + châu 3 màu + dây đèn + hộp quà nơ + bông tuyết đầy đủ; Quốc khánh = cờ bay lượn sóng + pháo hoa 2 chùm + trống đồng mờ; Hè = mặt trời 2 lớp + dừa 3 tán + phao cứu sinh sọc + sóng 3 lớp + mây; Đông = người tuyết (khăn + mắt + cà rốt) + thông tuyết mờ + flake lớn 2 nấc + đụn tuyết; Halloween = mạng nhện góc + bí ngô múi cười + mũ phù thuỳ tím + dơi + kẹo + sao; Trung thu = trăng crater + thỏ ngọc mờ + đèn lồng tua rua + đèn ông sao viền đỏ + mây; Tựu trường = bút chì gọt + chồng sách 3 màu + bảng xanh kẻ chữ + mũ tốt nghiệp + máy bay giấy + kính lúp. (3) Trang admin Theo mùa có HÌNH SAMPLE từng mùa (assets/img/seasonal/*.jpg 8 ảnh ~35KB chụp Playwright thật từ home 1920) + nút "Xem thử ngoài web ↗" mỗi mùa:?td_preview_preset=<key>- filter tandoanh_active_preset trả preset preview CHỈ cho user manage_options (khách không thấy), enqueue tự nạp asset theo, script wp_head prio 2 ép data-preset thắng localStorage, keyoffxem giao diện tắt. Verify: 8/8 preset strip+ribbon+motif OK sau v3, filter đúng cả 3 case (key thật/off/sai). - Fix ký tự hỏng double-encode (mất backslash) - chuỗi
&/\ntrong block JSON bị strip\từ lần lưu không wp_slash trước đây → hiển thị "Build u0026amp; test 24h", benchmark preset buildband dính 1 dòng. Sửa DB: home 6293 (ticker + features "Build & test 24h" + zones "Ryzen & Radeon" + buildband preset Văn phòng khôi phục 4 dòng benchmarks + costRows 2 dòng) và nav Vertical Menu HTML 104248 (8 label "Tanks & Accessories"…). Ghi lại bằngwp_update_post(wp_slash(...))chuẩn; verify live hết "u0026", JSON parse OK, mega menu label đúng "&". - Fix icon rớt dòng khối "Tương thích socket…" (buildband) - reset toàn cục
svg{display:block}(base.css) đẩy icon tick xuống dòng riêng → thêm.td-bp__ok svg{display:inline;vertical-align:-2px}(cả home.css lẫn home.purged.css); verify computed style svg inline + icon cùng dòng chữ. - QA agent 2 luồng (admin 18 trang + frontend 108 combo): admin - 0 lỗi console, 0 tràn, 0 .notice WP sai chỗ; frontend - 0 tràn ngang/108 combo 8 trang × 6 viewport × light/dark, drawer mobile 32/32 pass (mở + drill + back), trang /gioi-thieu/ + 3 band chính sách render đúng số/email/địa chỉ từ Business Info, 8 preset đủ decor; 2 cảnh báo "strip đè chữ" điều tra ra false positive (ticker full-bleed nền riêng; vùng vẽ strip cách chữ ≥74px). Findings thật đã fix: xem CHANGELOG tandoanh-buildpc 2.4.0 (fatal get_share + created_at + nút 36px). Ghi nhận KHÔNG sửa (chủ đích): input trong pill .ait-addon (Dịch ngôn ngữ) border:none vì pill ngoài đã viền 1.5px; nút icon 30px trang Trả góp là chủ đích theo thiết kế.
- Giao diện theo mùa v2 - (1) 8 mùa: thêm Halloween (cam bí ngô), Trung thu (đỏ đèn lồng + vàng trăng), Tựu trường (xanh bảng + vàng bút chì) - token AA pass 6/6 combo ngay từ đầu (btn 5.15-7.87). (2) Background trang trí 2 BÊN màn hình (≥1560px): SVG tile vẽ tay từng mùa (cành mai + lì xì / cây thông + tuyết / cờ sao / mặt trời sóng biển / bông tuyết / bí ngô + dơi + nhện / đèn lồng + trăng / bút chì + sách + mũ tốt nghiệp) đặt ở
body::before/::afterfixedz-index:-1(html không bg nên body bg thăng lên canvas → strip nằm TRÊN nền, DƯỚI mọi nội dung), bên phải soi gương scaleX(-1), opacity riêng dark. (3) Khung card KHÁC NHAU THEO KHU: khu TOP bán chạy (.td-tb) + section SP lẻ trên home = khung NGOẶC GÓC 2 tông + motif trên-phải; trang shop/danh mục/tìm kiếm + section SP chẵn = ruy băng ĐÁY + viền kép (outline -6px) + motif dưới-phải; còn lại = ruy băng đỉnh + motif dưới-trái (mặc định). (4) FX mới: Halloween lá thu + dơi (hạt thứ 4), Trung thu sao + đèn lồng phát sáng (hạt thứ 5), Tựu trường máy bay giấy vàng/mint. QA Playwright 1920px tet home+shop light/dark: strip 290px hiện đúng 2 bên, 26 hạt, 0 lỗi JS, 0 tràn. GOTCHA: sửa CSS đã bị WPFC combine thì PHẢIdeleteCache(true)(bundle bỏ ?ver - gotcha cũ tái diễn); selector khu C phải viết[data-preset] .archive ...vì data-preset trên html còn body class trên body. Ghi chú kỹ thuật trong file: .td-pcard::after thuộc woo-card.css - trang trí card chỉ đụng ::before + __media::after. - Trang Giới thiệu /gioi-thieu/ (page 104669) - template chết page-tan-doanh.html (slug trùng trang chủ, không bao giờ render) đổi thành page-gioi-thieu.html (main.tdp-about + wp:post-content); nội dung tdp-about chuyển vào page content (block-hoá đủ bộ hero/stats/story/values/services/visit); CSS bundle rename page-tan-doanh.css → page-gioi-thieu.css (nạp theo slug); 3 chỗ liên hệ hardcode trong section Showroom thay bằng shortcode
[td_biz](address + sales1/sales2 + email). Verify live 200, đủ markup + CSS + shortcode. Chưa gắn link menu/footer - chờ quyết vị trí. - Brand: đảo hết reader qua product_brand - PDP kicker (content-single-product.php) đọc term product_brand trước, fallback attribute cũ; Google Shopping settings đảo brand_source_taxonomy=product_brand / fallback=pa_thuong-hieu. Backfill check: 0 SP publish thiếu product_brand. QUYẾT ĐỊNH: KHÔNG xoá attribute pa_thuong-hieu (109 terms/3312 rels) - nó là "hộp thư đến" của bước đồng bộ real-time từ bản chính thức (
hp_sync_convert_brand()convert từng SP khi nhận, cần cả 2 taxonomy tồn tại); xoá là sync đẻ lại + mất đường rollback. Verify live: kicker PDP hiện brand từ taxonomy mới. - Giao diện theo mùa (Phase 11) - trang admin mới "Theo mùa" (
inc/admin/seasonal.php, TD Theme → Theo mùa): chọn 1 trong 5 preset (Tết / Noel / Quốc khánh / Hè / Đông) hoặc Mặc định (tắt), kèm toggle hiệu ứng rơi. Optiontandoanh_seasonal_preset+tandoanh_seasonal_fx; no-flash script trong enqueue.php đã đọc option này sẵn từ 1.6.x. Khi bật: card sản phẩm có ruy băng 2 tông sát mép trên + khung/nền nhuộm màu mùa (color-mix theo --td-brand nên tự đúng cả dark) + motif SVG góc ảnh (hoa mai/bông tuyết/sao/mặt trời - data-URI ~300 byte, nền media #fff cố định); hiệu ứng rơi (cánh đào/tuyết/sao/bong bóng nắng) doseasonal-fx.jstạo SAU window.load lúc idle, tối đa 26 hạt (mobile 14), transform compositor-only, tôn trọng prefers-reduced-motion.seasonal.css+ JS chỉ nạp khi preset bật → ngày thường 0 chi phí PSI. AA re-check toàn bộ token preset (tokens.css): 7/10 combo cũ rớt (chữ trên nút 2.17-4.22) → chỉnh đậm brand (tet #cc231f, quoc-khanh #ad1a14, he #d96407, dong #276aa5) + thêm on-brand tối cho dark (noel/quoc-khanh/dong) - sau sửa 10/10 combo preset × light/dark đạt AA (nút ≥4.97, chữ strong ≥4.50, UI ≥3.0). QA Playwright /shop/ noel light+dark: ribbon/motif/26 hạt hiện đúng, 0 lỗi JS, 0 tràn ngang. GOTCHA vận hành:wp option updatebằng root CLI bị race alloptions Redis (option ghi DB nhưng www-data đọc cache cũ, wpfc rename cache dir cũng Permission denied) → thao tác option + xoá cache PHẢI chạysudo -u www-data wp evalkèmwp_cache_delete("alloptions","options"). - Block
tandoanh/biz-text- địa chỉ/hotline/email đọc Business Info (td_biz), hết hardcode trong template chính sách. 3 biến thể:inline(1 giá trị, tuỳ chọn bọc tel:/mailto:),cta(band eyebrow + đoạn văn có token{address}/{hq}/{name}+ nút Gọi + nút email, namespace tdp-policy/tdp-payoo),contact(band lưới thẻ liên hệ trang chính sách - thẻ mặc định Kinh doanh ×2 / Kế toán / Email / Địa chỉ). Kèm shortcode[td_biz field="..." link="1"]cho INLINE trong nội dung trang (delegate qua block). Đã thay 3 band wp:html hardcode: page-chinh-sach-bao-hanh (CTA warranty + baohanh@), page-chinh-sach-van-chuyen (contact grid), page-bang-chi-phi-thanh-toan-tra-gop-payoo (CTA sales1 + kinhdoanh@) - verify live cả 3 trang render đúng số/email/địa chỉ từ Business Info. Business Info bổ sung email keybaohanh(baohanh@tandoanh.vn - số liệu đang dùng công khai trên trang bảo hành). Hotline hiển thị ưu tiêndisplay_header, fallbackdisplay. - Benchmark dựng phim (PugetBench, điểm Overall Score Standard): thêm 4 category
gpu_premiere/cpu_premiere/gpu_davinci/cpu_davinci(30 device mỗi app). Tab Hiệu năng VGA thêm "Dựng phim · Premiere Pro" + "Dựng phim · DaVinci"; CPU thêm 2 chỉ số tương ứng (chỉ hiện khi đủ ≥3 CPU cùng dòng có dữ liệu). - Promo Subscribers chia 2 tab: "Danh sách đăng ký" (bảng cũ: tìm kiếm/CSV/xoá) + tab mới "Soạn email marketing" (
inc/admin/promo-email.php): 3 mẫu soạn sẵn (Khuyến mãi / Hàng mới về / Giới thiệu trang) tự điền tiêu đề + lời nhắn có token{ten}thay tên từng khách; đính kèm sản phẩm (tìm AJAX theo tên, chip có ảnh), danh mục sản phẩm, trang/landing page; nút CTA tuỳ chỉnh. Email HTML chuẩn table + inline style (600px) theo brand gold ngoài site (theme.json: gold #e3c56e / #8a6a00, ink #15151a - không dùng màu admin): header ink logo gold + hotline + gạch gold, eyebrow accent theo mẫu, card sản phẩm ảnh nền surface + giá gold (hàng giá 0 tự thay "Giá liên hệ"), pill danh mục tông gold, CTA gold kiểu nút "Mua ngay" + dòng hotline phụ, footer ink social links, preheader ẩn cho dòng preview hộp thư; địa chỉ/hotline/social đọc từ Business Info (td_biz). Xem thử trong iframe, gửi thử tới 1 email, gửi tất cả theo batch 25 người/lượt có tiến trình. Mỗi email kèm link huỷ đăng ký ký HMAC - khách bấm là tự xoá khỏi danh sách (đã test end-to-end, chữ ký sai trả 400).
Giao diện
- Mega Menu: trình sửa viết lại thành dạng trực quan giống hệt mega menu ngoài trang chủ - pane trái là danh sách mục chính, pane phải là panel (cột nhóm / danh sách phẳng đúng luật render frontend); click bất kỳ chữ nào mở hộp thoại sửa nhãn/URL kèm dời thứ tự + xoá. Đã verify lưu cấu hình xong HTML mega menu ngoài trang không đổi 1 byte (vá luôn 2 lệch tiềm ẩn của chế độ config cũ: script sắp cột "Linh kiện ráp máy" và 5 cột đặc thù panel VGA).
- Admin thống nhất tông xanh theo header gradient (#1a2e4a → #2563eb): bỏ toàn bộ accent vàng/gold rải rác - icon trang Thanh toán + Trả góp, tiêu đề nhóm Popup, viền focus Contact Footer, accent + badge số Mega Menu, badge nhóm "Hiệu năng" trang Tính năng, tag MED trang Tốc độ. Màu đỏ (lỗi) và xanh lá (ổn) giữ nguyên vì mang nghĩa trạng thái.
- Thử 2 skin admin (gold editorial, navy) trong ngày rồi gỡ cả hai - giữ style gốc, chỉ chuẩn hoá màu như trên.
- Menu "Thông tin DN" đổi thành "Business Info" - đồng bộ tiếng Anh với các mục còn lại của menu TD Theme.
- Header mọi tab admin viết lại theo một công thức thống nhất cho người không kỹ thuật: trang này quản cái gì ngoài web → bạn làm được gì → sửa xong ảnh hưởng chỗ nào. Áp dụng 12 trang: Dashboard, Tốc độ, Mega Menu, Trang chủ, Contact Footer, Thanh toán, Trả góp, Popup, Dịch ngôn ngữ, Tính năng (ghi rõ chỉ để tra cứu), Subscribers, Benchmark Data (bỏ tên bảng kỹ thuật khỏi mô tả); bỏ các từ ngữ dev ("native", "FSE", "dock", tên plugin) khỏi phần mô tả.
- QA + chuẩn hoá control toàn admin (13 trang, audit script đo computed style - 0 vấn đề): luật chung trong admin.css - MỌI ô nhập/dropdown/textarea có viền 1.5px + bo 8px + cao 40px (không phụ thuộc từng trang gắn class); mọi nút
.hplt-btncao tối thiểu 40px canh giữa; nút WP.button(Chọn logo/Gỡ/×) khoác kiểu hplt. Sửa cụ thể: Installment - ô "Mức tối thiểu" tự format dấu chấm nghìn khi gõ (3000000 → 3.000.000, server vẫn nhận đúng), nút × xoá ngân hàng thành icon 40px, nút "Chọn logo"/"Gỡ" thay bằng icon FontAwesome (ảnh/×) 30px nằm NGANG HÀNG với logo; ô Mức tối thiểu thu còn 104px, padding bảng ngân hàng giảm (12px → 7/6px) cho gọn; Contact - tách "Bật dock" và "Độ trễ" bằng kẻ ngang + khoảng cách; Soạn email - card mẫu rộng 240px hết rớt chữ "sự kiện"; Benchmark Data pager đồng bộ 40px. - Notice WP (class
.notice) ở trang Mega Menu + Trang chủ bị WordPress tự bốc lên sau H1 → hộp trắng chèn giữa header xanh; đổi sanghplt-noticecủa theme (WP không di chuyển) - notice giờ nằm gọn dưới header, đúng style admin. - Nút đặt trong header card (vd "Xuất CSV" trang Subscribers): icon hết tàng hình (rule
.hplt-card__head .fa-solid{color:#fff}đè icon trắng trên nút nền trắng → scopedcolor:inherit), hover đổi sang nền sáng#dbeafethay vì#2563ebtrùng màu header (nút chìm mất vào nền).
Sửa lỗi
- QA 3 landing page (pc-gaming / ai-workstation / creator-studio): creator-studio có 98 rect waveform height ÂM bake sẵn trong landing-clone HTML (generator tính sin không clamp) → mỗi lượt xem log 98 lỗi console, bar tàng hình; fix chuẩn hoá
height=|h|, y=y+h(bar hướng lên từ đường giữa). Sau fix: 0 lỗi JS cả 3 trang × light/dark. QA kèm: 24 combo (4 viewport × 2 mode × 3 trang) 0 tràn ngang; hover 42 element tương tác 0 lỗi chữ-trùng-nền; PSI Perf 94-99 / A11y 100 / BP 100 / CLS≈0 (SEO 66 do staging chặn index cố ý); riêng pc-gaming mobile LCP ~4.4s vì clone 502KB + 2.039 phần tử SVG - ghi nhận chờ port block-native. - Icon Instagram ở footer hiện thành khối trắng đặc: rule global
svg { fill: currentColor }(base.css) đè thuộc tínhfill="none"của icon outline → đổi thànhsvg:not([fill="none"]), sửa cả base.purged.css. QA footer 10 viewport × light/dark: 0 tràn ngang, layout 1/2/4 cột đúng breakpoint. - Card trạm NVIDIA (RTX 5880/4500/3500 Ada) lọt bảng "so sánh cùng dòng" của card gaming dưới tên cụt "RTX 5880": extractor giữ suffix Ada (tên hiển thị đúng "RTX 5880 Ada") + meta chặn số dạng x8xx khỏi họ consumer.
- Tiêu đề card so sánh "Năng lực AI so với các card cùng dòng" đổi thành "Hiệu năng làm việc so với các card cùng dòng" - selector giờ gồm cả render 3D + dựng phim, không riêng AI.
- Trang Thông tin DN fatal PHP 8 (
"$n[key]"trong chuỗi kép = truy cập offset chuỗi) - 16 chỗ đổi sang nối chuỗi.
Ghi chú
- Dọn lại CHANGELOG: gộp mỗi ngày một phiên bản, các entry cũ trong cùng ngày được gom lại.
[1.7.3] - 2026-07-07 (Hệ benchmark hiệu năng + refactor giảm hardcode)
Mới
- Trang admin "Thông tin DN" (option
tandoanh_business_info): công ty/MST/trụ sở, showroom, 6 hotline (hiển thị theo ngữ cảnh footer/header/PDP), email, giờ hoạt động, social + kênh chat PDP, 13 link chính sách, BCT/DMCA, năm ©. Helpertd_biz()/td_biz_hotline()/ aliastandoanh_contact()- thankyou.php hết hiện số giả "1900 000 000". Footer/topbar thành dynamic block đọc từ option, markup giữ nguyên từng byte, bản dịch /en/ nguyên vẹn; "người đang xem" random ổn định theo khung giờ (min/max chỉnh trong admin). - Hệ benchmark trong tab Hiệu năng - toàn bộ từ nguồn chính thức, kèm provenance:
- Render: Blender Open Data 5.1 (80 GPU + 210 CPU, median samples/phút theo scene), OctaneBench 2025 (162 GPU), V-Ray Benchmark v6 (598 GPU + 865 CPU, đã lọc single-socket/single-GPU).
- CPU: Geekbench 6 Đơn/Đa nhân (132 CPU, chip thiếu lấy median search n=50 - độ phủ CPU shop 100%), encode x265, nén 7-Zip, văn phòng CrossMark - tổng 9 chỉ số so sánh cùng dòng.
- AI: panel "Model AI phổ biến" (Can-I-Run LLM, 10 model 1.5B→32B, badge Chạy mượt/Chạy tốt/Tạm ổn, model vượt VRAM ghi "Cần VRAM lớn hơn") + chỉ số "Chạy LLM · Llama 3.1 8B".
- Fallback biến thể Intel F/KF ↔ bản gốc (cùng silicon, chỉ khác iGPU).
- reCAPTCHA v3 tự làm (module tandoanh-code/cf7-recaptcha-v3, thay plugin v2 bên thứ ba) cho CF7 Liên hệ + Tuyển dụng + form career; badge ẩn + notice Google, lazy-load chống TBT.
- PDP desktop: mô tả ngắn quá dài tự thu gọn + nút "Xem thêm".
Thay đổi
- Refactor giảm hardcode: bảng seed 32 ngân hàng trả góp về 1 nguồn
inc/tragop-data.php; gói quà mặc định về 1 hàm; icon SVG registryinc/icons.phpdùng chung 10 bộ (render byte-identical, verify md5); chuỗi UI lặp bọc__(); text tiếng Việt trong JS chuyển quawp_localize_script; nguồn newsband có filter. - Nút chat PDP chốt theo production: Messenger
m.me/TanDoanh(PC ra web) + deep-linkfb-messenger://nhảy thẳng app trên iOS/Android/iPad (bắt cả iPadOS mạo UA Macintosh); Zalo vềzalo.me/0783666668. Verify đủ 6 loại thiết bị.
Sửa lỗi
- Global
a:hoverđè màu chữ các nút (.td-btn / Mua ngay) thành xanh - loại nút khỏi a:hover (sửa cả base.purged.css); rà soát CSS sau QA (hover, contrast dark mode, buildpc). - Panel Model AI: chip nhiều biến thể VRAM (5060 Ti 8/16GB…) ưu tiên biến thể khớp VRAM trong tên sản phẩm, tránh hiện số của bản VRAM lớn hơn.
- Gỡ card "Cho thuê PC, máy chủ render" trỏ link chết trong template tan-doanh (code chết, không còn render).
[1.1.8] - 2026-07-05 (Trung tâm điều khiển admin + song ngữ VI/EN)
Thêm mới
- Menu quản trị "TD Theme" gom toàn bộ cấu hình theme về một chỗ: Dashboard (tình trạng hệ thống thời gian thực + truy cập nhanh + nhật ký), Tốc độ, Mega Menu, Trang chủ, Contact Footer, Thanh toán, Trả góp, Popup, Dịch ngôn ngữ, Đăng ký KM, Tính năng. Bộ giao diện thẻ/tab/modal/accordion đồng bộ, Font Awesome 6 local riêng cho admin.
- Mega Menu: trình sửa kéo/thả 3 cấp (mục chính → nhóm → liên kết) lưu option riêng, lần đầu tự nạp từ menu nguồn nên giống hệt hiện trạng; render giữ nguyên markup
.td-mega__*. - Contact Footer: dock liên hệ nổi cấu hình được (kéo-thả kênh, bật/tắt, icon media) - desktop pill dọc, mobile nút tròn bung kênh.
- Popup: banner theo trang với kiểu kích hoạt (ngay / sau N giây / cuộn tới % / thoát trang), cookie ẩn N ngày, phạm vi hiển thị linh hoạt; CSS/JS chỉ tải trên trang có popup khớp.
- Thanh toán: thiết kế lại dạng thẻ + công tắc, thêm tuỳ chọn "Mặc định bật hoá đơn VAT" (Tân Doanh ưu tiên xuất hoá đơn, hoạt động cả khi không có JS).
- Tính năng: trang liệt kê 27 tính năng theme theo nhóm, có bộ lọc + cửa sổ chi tiết + nút mở trang cấu hình; nguồn dữ liệu duy nhất
features-registry.php. - Tab "Trang chủ" viết lại thành bảng điều khiển trang chủ block (tổng quan section qua
parse_blocks(), chi tiết nhanh, nút mở trình sửa/Site Editor/xoá cache) - KHÔNG ghi đè nội dung trang chủ. - Song ngữ VI/EN
/en/SSR (SEO-friendly, opt-in mặc định TẮT): trang admin "Dịch ngôn ngữ" với công tắc tổng + 4 tab (Dịch nội dung / AI Providers đa nhà cung cấp có fallback / Cron tự dịch / Chuỗi giao diện); dịch tay ~120 chuỗi UI để giao diện /en/ tiếng Anh đầy đủ; hreflang + canonical phát ở wp_head.
Hiệu năng
- Hoãn JS bên thứ ba (GA/GTM/Facebook/Clarity) tới tương tác đầu hoặc 12 giây; defer WPFC Combined JS (bỏ chặn render ~1.350ms); trang Tốc độ tổ chức lại 5 nhóm tab với các tối ưu async CSS, tắt Cart Fragments, emoji, preconnect, preload font.
- Sửa CLS trang chủ 0.6 → 0: defer Combined JS bỏ qua trang chủ vì hero slider cần JS sớm (trang khác vẫn defer).
Thay đổi
- Cập nhật biểu phí trả góp Payoo chính thức: 32 ngân hàng, 8 kỳ hạn (trước 23 ngân hàng, 5 kỳ hạn); phí cà thẻ 1.833% → 1.8%.
- Dark mode 3 trạng thái (Theo hệ thống / Sáng / Tối); sắp lại thứ tự menu admin; dời "Đăng ký KM" từ menu WooCommerce về TD Theme.
[0.9.9.9] - 2026-07-04 (Landing + trang chủ)
Thêm mới
- 3 trang landing riêng: PC Gaming, AI Workstation, Creator Studio - 5 block editable, SVG mockup động theo biến thể.
- Block
tandoanh/newsband: 4 bài mới nhất từ news.tandoanh.vn (cache 30 phút, ảnh chỉ tải trên desktop).
Thay đổi
- Khối danh mục nổi bật trang chủ chuyển sang 8 tile, thêm icon CPU/Mainboard/VGA/RAM/SSD.