VosCMS Cửa Hàng

Nhật ký thay đổi

v2.8.2 2026-10-12 · 7 ngày trước
Màn hình cập nhật và lịch sử thay đổi hiển thị theo ngôn ngữ của người xem

Những gì đã được sửa

  • •Lỗi của trình cập nhật: ghi tệp và version.json thất bại, không hỗ trợ bản vá và xem trước thay đổi, không truy cập được kho lưu trữ và kết nối thành công.
  • •Màn hình cập nhật: lỗi phản hồi máy chủ, «N tệp thay đổi · N commit», hoàn tất, đang áp dụng, đã đăng ký tác vụ, quá thời gian và khôi phục hoàn tất.
  • •Thông báo đăng ký tác vụ: thông báo rằng tác vụ cập nhật, vá hoặc khôi phục đã được xếp hàng.
  • •Worker có quyền (cron) giờ đây để lại thông báo tiến độ cùng thông báo thành công và thất bại bằng đúng ngôn ngữ.

Màn hình lịch sử thay đổi (`/changelog`)

  • •Thời gian tương đối như «5 months ago» trước đây chỉ có tiếng Hàn và tiếng Anh; nay có 13 ngôn ngữ.

Thông báo danh sách trống, nhãn «Bản dịch AI», ghi chú «chưa có bản dịch — hiển thị bằng KO» và «chỉ hiển thị N mục mới nhất» cũng được dịch.

  • •Ngôn ngữ màn hình giờ lấy theo ngôn ngữ mà trang web thực sự dùng, không chỉ giá trị phiên (?lang=, phiên, cookie, ngôn ngữ mặc định).

Trước đây lần truy cập đầu tiên rơi về tiếng Hàn nên nhãn tiếng Hàn lẫn vào các trang tiếng Nhật và tiếng Anh.

  • •Định danh và đường dẫn dài (văn bản không có khoảng trắng) không còn tràn ra ngoài thẻ hay chui xuống dưới nút cài đặt bên phải.

Cần biết

  • •Worker có quyền không có người dùng đăng nhập nên không có ngôn ngữ. Nó ghi thông báo bằng ngôn ngữ mặc định của trang web.

(Trước đây nó không khởi động hệ thống dịch nên các khóa như updater.write_failed có thể bị in ra nguyên văn. Nay worker đã khởi động hệ thống này.)

  • •Nhật ký máy chủ (error_log) và nhật ký gỡ lỗi dành cho nhà phát triển do người vận hành đọc nên được giữ nguyên.
  • •Trên trang web đã cài đặt, bên chạy cập nhật là trình cập nhật cũ đã được cài sẵn, vì vậy các cải tiến này lần đầu xuất hiện ở lần cập nhật sau khi chuyển lên 2.8.2.
v2.8.1 2026-10-12 · 7 ngày trước
Tăng cường đa ngôn ngữ (tên ứng dụng, dữ liệu tìm kiếm, `?lang=`) · bản cập nhật bảo vệ các thay đổi lõi của riêng từng trang web

Đa ngôn ngữ

  • •Tên và mô tả ứng dụng trong «Thêm vào màn hình chính» và lời nhắc cài đặt giờ hiển thị theo ngôn ngữ của người xem. Trước đây giá trị đã lưu (ví dụ tiếng Nhật) được hiển thị nguyên như vậy.

Bản dịch được đặt dưới các khóa như pwa.front.name trong rzx_translations. manifest.php nay chỉ chuyển giao cho đầu ra chính thức.

  • •Dữ liệu có cấu trúc (JSON-LD): xem bản dịch của các giá trị cài đặt trước. Đã sửa mục thứ hai của breadcrumb có kèm cả tên trang web, và «Home» hiển thị bằng tiếng Anh ở mọi ngôn ngữ.
  • •Widget thống kê: con số và đơn vị (suffix) giờ cũng nhận giá trị theo từng ngôn ngữ như nhãn. Giá trị đơn vẫn hoạt động y như trước.
  • •Màn hình ngoại tuyến và dòng thông báo cuối cùng của service worker nay có tiếng Hàn, tiếng Nhật và tiếng Anh.

Phiên bản bộ nhớ đệm của service worker tăng từ v5 lên v6 để các thiết bị đã cài ứng dụng nhận được màn hình mới.

  • •«Không có kết quả» trong tìm kiếm tin nhắn từng được viết thẳng bằng tiếng Hàn; nay có 13 ngôn ngữ.

Công cụ tìm kiếm và AI

  • •Xuất <meta property="og:locale"> và các ngôn ngữ thay thế (og:locale:alternate). Khi chia sẻ trên mạng xã hội, nó cho biết trang đó dùng ngôn ngữ nào.
  • •Các trang hệ thống công khai do mã vẽ nên giờ cũng có trong sitemap.xml (trước đây bị thiếu).
  • •Dòng đầu tiên của llms.txt (mô tả trang web) hiển thị theo ngôn ngữ của người xem.
  • •Cài đặt robots theo từng trang (màn hình quản trị có ô nhập nhưng không nơi nào đọc nó) giờ thực sự được áp dụng.

Các vấn đề đã sửa

  • •Giá trị ?lang= chỉ được chấp nhận sau khi đối chiếu với danh sách ngôn ngữ được hỗ trợ. Trước đây giá trị không được hỗ trợ lưu trong cookie suốt một năm,

và khi mở ngôn ngữ đó về sau, người truy cập có thể bị chuyển sang màn hình ấy ngoài ý muốn. Bộ chọn ngôn ngữ cũng theo cùng quy tắc.

  • •Trình tạo widget: bản dịch của những ngôn ngữ không có ô nhập trên màn hình bị xóa mỗi lần lưu.
  • •Tìm kiếm tin nhắn cộng đồng: tên được lưu ở dạng mã hóa nên nhập tên nào cũng ra 0 kết quả. Nay hệ thống giải mã trước rồi mới đối chiếu.

Bản cập nhật bảo vệ các thay đổi lõi của riêng từng trang web

  • •Nếu bạn ghi các đường dẫn vào storage/custom/update-preserve.txt, mỗi dòng một đường dẫn (# là chú thích, có thể dùng thư mục), bản cập nhật sẽ không ghi đè các tệp đó.

Dùng để bảo vệ những gì bạn đặt trực tiếp vào tệp lõi, chẳng hạn quy tắc đăng nhập riêng của trang web. Đường dẫn tuyệt đối và .. không được chấp nhận,

và nếu không đọc được tệp, bản cập nhật không dừng lại mà tiếp tục với danh sách bảo vệ mặc định.

  • •Cần biết: bên chạy cập nhật phải đã có tính năng này thì mới hưởng lợi. Nó áp dụng từ lần cập nhật sau khi chuyển lên 2.8.1.
v2.8.0 2026-10-12 · 7 ngày trước
Thêm nhà cung cấp thanh toán (PG) chỉ bằng cách thả một thư mục · hỗ trợ Square

Có gì thay đổi

Mô-đun thanh toán vốn đã có một tệp riêng cho từng nhà cung cấp, nhưng «có những nhà cung cấp nào» lại được viết ở nhiều chỗ trong mã.

Để thêm một nhà cung cấp, phải sửa trình quản lý thanh toán, màn hình cài đặt và webhook.

  • •Hãy đặt thư mục (gateway.json cùng tệp triển khai) vào rzxlib/Modules/Payment/Gateways/ và lõi sẽ tự nhận ra nó.

Lựa chọn nhà cung cấp, các ô khóa và địa chỉ webhook trên màn hình cài đặt quản trị được tạo từ bản đặc tả đó.

  • •Trang web vẫn chọn một nhà cung cấp trên màn hình cài đặt (như trước). Đây không phải tính năng dùng nhiều nhà cung cấp cùng lúc.
  • •Cách thêm nhà cung cấp được ghi trong docs/PAYMENT_GATEWAYS.md.

Square

  • •Hỗ trợ thanh toán bằng thẻ, hoàn tiền và tra cứu, thẻ đã lưu (cho thanh toán định kỳ) và webhook (có xác minh chữ ký).
  • •Biểu mẫu nhập thẻ đi qua xác thực chủ thẻ (SCA) và hiển thị lý do trên màn hình khi thất bại. 13 ngôn ngữ.
  • •Màn hình cài đặt quản trị có nút mới «Kiểm tra kết nối». Ở chế độ thử nghiệm, nút này chạy một giao dịch nhỏ, tra cứu và hoàn tiền

để xác nhận khóa của bạn đúng. Không có tiền thật được chuyển, và nó không chạy ở chế độ thực (live).

  • •Cho đến khi bạn chọn Square, không có gì thay đổi với bất kỳ trang web nào.

Các nhà cung cấp hiện có (PAY.JP và Stripe) giữ nguyên

  • •Các tệp triển khai của hai nhà cung cấp này không bị đụng tới. Các cài đặt cũ (một khóa, v2, v3) vẫn được đọc như trước.
  • •Ngay cả khi vì lý do nào đó không đọc được các tệp đặc tả, một lớp bảo vệ khiến PAY.JP và Stripe vẫn được tạo theo cách cũ.
  • •Bằng các cài đặt thực của những trang web đang vận hành và nhiều cài đặt giả lập, chúng tôi đã so sánh mã cũ và mã mới và xác nhận chúng chọn cùng nhà cung cấp, cùng chế độ và cùng khóa

(scripts/test-payment-parity.php).

Đọc cài đặt thanh toán theo từng trang web

Khi một cơ sở dữ liệu chứa cài đặt thanh toán riêng cho từng trang web, mô-đun thanh toán nay đọc cài đặt của chính trang web đó.

Trước đây không xác định được cài đặt của trang web nào sẽ được chọn. Nếu một trang web không có cài đặt riêng, nó hoạt động như trước.

Cần biết

  • •Đã thêm một địa chỉ webhook dùng chung (/api/webhook-payment.php?gateway=…). Địa chỉ webhook hiện có của PAY.JP và Stripe không thay đổi.
  • •Danh sách nhà cung cấp trên màn hình cài đặt giữ nguyên thứ tự cũ; các nhà cung cấp vào qua bản đặc tả được thêm vào sau.
v2.7.17 2026-09-21 · 28 ngày trước
Nội dung của plugin nay hiển thị với công cụ tìm kiếm và AI

Vấn đề là gì

Sơ đồ trang web (sitemap.xml) và hướng dẫn cho AI (llms.txt) chỉ chứa những gì lõi biết.

Để plugin thêm trang của riêng mình, cách duy nhất là sửa trực tiếp tệp lõi, và chỉnh sửa đó

biến mất sau mỗi lần cập nhật. Ngoài ra, lõi đoán cách đọc bảng plugin nên ở một số nơi đã âm thầm lệch đi.

  • •Bất động sản chỉ được xuất ra ở địa chỉ riêng (/properties-sitemap.xml); nếu không đâu trỏ tới địa chỉ đó,

công cụ tìm kiếm không thể tìm thấy.

  • •Các mặt hàng của chợ chưa bao giờ xuất hiện trong sơ đồ trang web, do câu truy vấn tìm một cột không tồn tại.

Lỗi bị nuốt mất nên không ai biết.

  • •Một số trang web đưa địa chỉ cửa hàng vào ở dạng sai, khiến công cụ tìm kiếm lập chỉ mục những địa chỉ mở ra trang không tồn tại.

Plugin nay tự xuất bản trang của mình

  • •Nếu plugin ghi seo trong plugin.json, lõi sẽ đọc và gộp vào sơ đồ trang web và hướng dẫn cho AI.

Cách hoạt động giống widget, bố cục và mô-đun intranet, và khi địa chỉ trùng nhau thì lõi thắng.

  • •Địa chỉ cho nhiều ngôn ngữ và nhãn ngôn ngữ do lõi tự thêm. Plugin chỉ cần đưa ra địa chỉ.
  • •Một plugin hỏng không còn làm sập cả sơ đồ trang web. Chỉ phần của plugin đó bị bỏ qua.
  • •Địa chỉ của plugin đã tắt tự động bị loại — trang của plugin đã tắt vốn cũng không mở được.

Địa chỉ thay thế tiếng Trung bị bỏ qua

Sơ đồ trang web ghi nhãn ngôn ngữ là zh_CN, trong khi chuẩn là zh-CN, nên Google bỏ qua toàn bộ dòng đó.

Bản thân các trang được ghi đúng, vì vậy cùng một trang web nói hai điều khác nhau ở hai nơi.

Địa chỉ thay thế cho tiếng Trung giản thể và phồn thể nay đã được nhận diện đúng.

Hướng dẫn cho AI theo từng ngôn ngữ

  • •llms.txt trước đây chỉ có một bản bằng ngôn ngữ mặc định. Nay nó xuất ra các bản theo ngôn ngữ như ?lang=en.

Tên và mô tả mặt hàng xuất ra bằng ngôn ngữ đó, và phần đầu hướng dẫn ghi rõ đó là bản ngôn ngữ nào.

  • •Trên các trang đa ngôn ngữ, công cụ trả lời của AI nay có thể giới thiệu trang web này cho người dùng ở từng khu vực ngôn ngữ.

Nhân viên có thể xem hồ sơ nhân sự của chính mình (intranet)

  • •Hồ sơ nhân sự trước đây chỉ người phụ trách nhân sự xem được nay chính nhân viên cũng có thể xem. Vào từ menu hồ sơ cá nhân ở phía trên.
  • •Chỉ có thể xem. Quy trình để yêu cầu chỉnh sửa và người phụ trách nhân sự phê duyệt đang được chuẩn bị.
  • •Đánh giá không hiển thị với chính nhân viên. Khen thưởng và kỷ luật cũng vậy. Với tài liệu đính kèm, chỉ hiển thị danh sách.
  • •Không thể mở hồ sơ của người khác bằng cách sửa thanh địa chỉ — hồ sơ của ai chỉ được quyết định bởi thông tin đăng nhập.
  • •Nhân viên cũng có thể kiểm tra ai đã xem thông tin nhân sự của mình.
v2.7.16 2026-09-21 · 28 ngày trước
Địa chỉ gốc của liên kết diễn đàn và bố cục trong plugin

Dùng màn hình diễn đàn trong một lớp vỏ khác

Mọi liên kết trên màn hình diễn đàn đều được tạo từ một giá trị duy nhất ($boardUrl), nhưng lõi luôn ghi đè giá trị đó.

Vì vậy, bên dùng diễn đàn bên trong màn hình quản trị như intranet phải thay thế từng ký tự trên trang đã được dựng xong.

Chỉ cần lõi đổi dạng của liên kết một chút là mọi thứ âm thầm lệch đi.

  • •Nếu bên gọi quyết định địa chỉ gốc trước, giá trị đó được dùng. Nếu không, mọi thứ giống hệt trước đây.
  • •Liên kết bánh răng (cài đặt diễn đàn) cũng được quyết định ở một nơi. Trước đây danh sách, FAQ, Hỏi đáp và giao diện liên kết mỗi nơi tự tạo một liên kết.

Bố cục có thể nằm trong plugin

  • •Bố cục được tìm trước ở skins/layouts/ của lõi, nếu không có thì ở plugins/{id}/skins/layouts/ của plugin.

Quy tắc giống widget và mô-đun intranet, và khi tên trùng nhau thì lõi thắng.

  • •Bố cục của plugin cũng xuất hiện trong bộ chọn bố cục của quản trị.
  • •Cho đến nay, bố cục dành riêng cho plugin phải đặt trong thư mục lõi. Cập nhật không xóa nó,

nhưng nếu sau này lõi phát hành bố cục cùng tên thì nó bị ghi đè, và khi chuyển plugin sang trang khác phải mang thư mục theo bằng tay.

v2.7.15 2026-09-21 · 28 ngày trước
Plugin khai báo mô-đun intranet · niên hiệu Nhật Bản khi nhập ngày

Plugin tự khai báo mô

Danh sách cho các màn hình intranet (menu trái và đường vào) trước đây chỉ có trong một tệp cài đặt của lõi.

Để plugin thêm mô-đun của riêng mình, phải sửa một tệp lõi, và nội dung đó biến mất khi cập nhật.

  • •Nếu plugin ghi intranet_module trong plugin.json, lõi sẽ đọc và gộp lại. Cách hoạt động giống menu và trang hệ thống.
  • •Giá trị có thể là một mảng ghi trực tiếp, hoặc một đường dẫn tệp như "data/intranet-module.php".
  • •Khi tên trùng nhau thì lõi thắng. Plugin không thể chiếm quyền mô-đun của lõi để đổi hành vi mặc định.
  • •Cả năm nơi trong lõi từng đọc danh sách này đều đã chuyển sang cách mới. Dù cập nhật ghi đè tệp cài đặt, mô-đun của plugin vẫn còn.

Niên hiệu Nhật Bản (和暦) khi nhập ngày

  • •Trên màn hình tiếng Nhật, nếu chọn niên hiệu (令和, 平成, 昭和, 大正, 明治) và nhập số năm vào ô ngày, năm dương lịch sẽ tự động được điền.

Những giá trị nhớ theo niên hiệu như ngày sinh không cần phải quy đổi mỗi lần.

  • •Ô hiển thị thứ trong tuần được giữ nguyên.

Cài đặt bố cục diễn đàn không phản ánh lên màn hình

  • •Dù đã chọn bố cục cho từng diễn đàn trong quản trị, màn hình vẫn hiển thị bố cục mặc định của trang web.

Nơi lưu và nơi đọc khác nhau.

  • •Cách sửa: khi lưu diễn đàn, cài đặt mà màn hình đọc cũng được ghi cùng lúc.

Các diễn đàn hiện có giữ nguyên diện mạo như bây giờ cho đến khi được lưu lại (diện mạo không đột ngột thay đổi).

v2.7.14 2026-09-20 · 29 ngày trước
Viết bài và tìm kiếm diễn đàn trở lại bình thường

Bài viết không được lưu khi viết

  • •Việc lưu bài viết bỏ qua cột tiêu đề, nên ở những trang web còn cột đó thì lưu thất bại.

Màn hình chỉ hiện "Unexpected end of JSON input".

  • •Cách sửa: nếu cột còn tồn tại thì cũng điền vào. Những trang đã xóa cột hoạt động như trước.

Tìm kiếm diễn đàn

  • •Tìm kiếm nhìn vào cột cũ, nên ở những trang đã xóa cột, cả danh sách không mở được ngay khi nhập từ khóa.
  • •Những trang còn giữ cột cũng gặp vấn đề. Sửa bài viết không cập nhật cột, nên tìm kiếm chỉ khớp với nội dung trước khi sửa.
  • •Cách sửa: tìm kiếm trong bảng dịch. Nay nó tìm được cả ngôn ngữ đang xem lẫn nội dung đã dịch.

Bài viết không hiện trong danh sách, widget và Trang của tôi

  • •Widget tab lĩnh vực hoạt động và widget lưới diễn đàn luôn hiển thị danh sách trống (lỗi bị nuốt bên trong).
  • •Trong "Bình luận của tôi" ở Trang của tôi, bình luận diễn đàn bị thiếu hoàn toàn.
  • •Giao diện diễn đàn liên kết luôn có tiêu đề trống.
  • •Cách sửa: tất cả nay đọc tiêu đề và nội dung từ bảng dịch. Ảnh thu nhỏ cũng được tìm lại từ nội dung.

Dịch AI và cài đặt mới

  • •Chúng tôi đã sửa lỗi dịch AI cho bài viết bị thất bại khi đọc văn bản gốc, khiến mọi tác vụ dịch đều thất bại.
  • •Chúng tôi đã sửa lỗi khi cài đặt mới, tiêu đề và nội dung bằng ngôn ngữ gốc của các bài viết mẫu không được đưa vào bảng dịch nên tiêu đề trông như trống.

Khác

  • •Chúng tôi đã sửa trường hợp danh sách không mở được khi sắp xếp diễn đàn đặt là "theo đề xuất" (tham chiếu tới một cột không tồn tại).
v2.7.13 2026-09-20 · 29 ngày trước
Hộp thông báo quản trị an toàn hơn · Đa ngôn ngữ

Chữ của người khác được đưa thẳng vào hộp thông báo

Hộp thông báo dùng chung trong màn hình quản trị (hộp kết quả) dán thẳng tiêu đề menu, tên giao diện và thông điệp từ máy chủ vào trang.

Chỉ cần đặt tên chứa <script>, nội dung đó có thể chạy khi quản trị viên khác mở màn hình ấy (XSS lưu trữ).

  • •Đã sửa: mọi đoạn chữ trong hộp thông báo (tiêu đề, nội dung, nút, câu xác nhận) đều được chuyển thành ký tự thường trước khi chèn.
  • •Thông báo khi không kết nối được cơ sở dữ liệu nay dùng bản dịch và cũng qua bước chuyển đổi này.

Nút trong hộp thông báo hiện tiếng Hàn ở mọi ngôn ngữ

  • •"Xác nhận" và "Huỷ" bị viết cứng bằng tiếng Hàn trong JavaScript. Nay hiển thị theo ngôn ngữ đang xem.

Máy chủ chuẩn bị câu chữ của ngôn ngữ hiện tại, mã lệnh chỉ đọc lại giá trị đó.

Câu chữ quản trị cho 13 ngôn ngữ

Các câu tiếng Hàn viết cứng trong màn hình thiết kế (giao diện), menu và thiết lập trang đã được thay bằng khoá dịch và bổ sung đủ 13 ngôn ngữ.

  • •Giao diện: kết quả đổi tên, nhân bản, xoá; câu xác nhận "tệp và thiết lập giao diện sẽ bị xoá vĩnh viễn"; kết quả tải ảnh lên
  • •Menu: thông báo trang hệ thống chỉ được gỡ khỏi menu; câu xác nhận "trang liên kết (diễn đàn) cũng bị xoá"
  • •Thiết lập trang: thông báo về loại tệp, lưu thất bại và URL trùng
v2.7.12 2026-09-19 · 1 tháng trước
Bảo vệ bài viết riêng tư · Hiển thị đầu tiên nhanh hơn

Bài viết riêng tư bị lộ qua danh sách

Bài đặt riêng tư vẫn hiện tiêu đề, ảnh đại diện và đoạn tóm tắt trong danh sách. Chỉ phần nội dung bị ẩn.

  • •Đã sửa: trong danh sách cũng vậy, chỉ tác giả, quản trị viên hoặc người nhập đúng mật khẩu mới thấy tiêu đề và bản xem trước.
  • •Đã chặn cả việc xem nội dung qua địa chỉ tệp đính kèm; tệp đính kèm nay áp dụng cùng một kiểm tra.
  • •Tiêu đề bài trước/bài sau trên trang đọc cũng được ẩn.
  • •Các widget lấy danh sách (thẻ diễn đàn, lưới, tab) loại bài riêng tư ngay từ truy vấn.

Màn hình đầu tiên hiện quá chậm

Trên điện thoại, chữ đầu tiên xuất hiện rất lâu. Nguyên nhân là phông chữ.

  • •CSS phông chữ (Google Fonts 152KB + Pretendard 29KB) đang chặn việc vẽ trang.

Nay trang vẽ trước bằng phông hệ thống, phông web thay vào khi tải xong.

  • •Pretendard chỉ tải trên màn hình tiếng Hàn. Màn hình tiếng Nhật ưu tiên phông Nhật nên trước đây chỉ tải mảnh rồi bỏ.
  • •Hai tệp kiểu nhỏ (cỡ chữ, nội dung diễn đàn) được nhúng thẳng vào trang thay vì tải riêng.
  • •Ở lần truy cập đầu, bộ nhớ đệm màn hình (service worker) khiến tài liệu bị đọc hai lần — đã loại bỏ.
  • •Việc tính bề rộng của menu cuộn ngang được dời đến sau khi trang tải xong (trước đây làm đứng trang 0,5 giây).

Để robot tìm kiếm và AI theo được trang theo ngôn ngữ

  • •Liên kết đổi ngôn ngữ nay trỏ tới địa chỉ thật (?lang=…). Trước là liên kết JavaScript nên robot không theo được.

Màn hình quản trị

  • •Danh sách trang hiển thị cùng một trang thành nhiều dòng theo số ngôn ngữ; nay gộp lại thành một dòng.
  • •Chỉ sửa tiêu đề menu lại làm mất bản dịch của các ngôn ngữ khác. Nay chỉ dọn bản dịch khi đổi trang liên kết.
  • •Hẹn giờ đăng blog vào thời điểm đã qua trước đây vẫn lưu như vậy; nay hiện thông báo và giữ nguyên trạng thái (13 ngôn ngữ).

Thông báo và câu chữ

  • •Tiêu đề thông báo tin nhắn cộng đồng bị cố định bằng tiếng Hàn. Nay gửi theo ngôn ngữ của người nhận.
  • •Chữ liên kết trên thanh thông báo cookie quá tối, đã chỉnh sáng hơn.

Dọn dẹp nội bộ

  • •Đã xoá các thư mục giao diện quản trị bị sao chép trùng (admin/site/site, admin/components/components).

Thư mục thực sự dùng là bản gốc. Bản dựng phân phối cũng loại trừ các thư mục này.

v2.7.11 2026-09-13 · 1 tháng trước
Loại bảng tin riêng tư khỏi sitemap · Cải thiện khả năng gửi email

Bảng tin riêng tư bị đưa vào sitemap

Ngay cả địa chỉ của các bảng tin chỉ quản trị viên mới xem được (như hộp tiếp nhận yêu cầu) cũng bị đưa vào sitemap.

Robot tìm kiếm chỉ nhận được lỗi 403 (cấm truy cập) từ các địa chỉ đó, và việc có bảng tin riêng tư cũng bị lộ ra.

  • •Khắc phục: chỉ đưa vào những bảng tin mà người không phải thành viên có thể xem. Tiêu chí là các bảng tin có quyền xem danh sách và đọc bài viết được đặt là "Tất cả".
  • •Bài viết bí mật và bảng tin được đặt loại khỏi tìm kiếm (noindex) trong phần cài đặt bảng tin cũng bị loại ra.
  • •Trang có cùng tên với bảng tin sẽ được xét theo bảng tin, vì bảng tin chiếm địa chỉ trước.
  • •Các trang đa ngôn ngữ cũng được đưa vào sitemap.
  • •Những trang không muốn đưa vào cho từng website có thể ghi vào cài đặt sitemap_exclude. llms.txt cũng tuân theo cài đặt này.

Email gửi đi bị vào thư rác hoặc bị trả lại

  • •Email thiếu thời điểm gửi (Date) và mã định danh duy nhất (Message-ID), nên phía nhận dễ phân loại là thư rác.

Nay cả hai đều được thêm vào, và phần nội dung được gửi dưới dạng base64. Việc này cũng ngăn dòng dài bị cắt và nội dung bị ngắt do dấu "." ở đầu dòng.

  • •Khi địa chỉ nhận cùng tên miền với địa chỉ gửi (ví dụ bản sao gửi về địa chỉ công ty), hộp thư của tên miền đó đã từ chối vì coi là giả mạo.

Chỉ trong trường hợp này, email được gửi từ địa chỉ tài khoản SMTP, còn thư trả lời vẫn về địa chỉ ban đầu.

Tăng cường cài đặt SEO và tìm kiếm bằng AI

  • •Đã thêm các ô thông tin đơn vị vận hành (dữ liệu có cấu trúc Organization) vào cài đặt SEO của trang quản trị. Mục không có giá trị sẽ không được xuất ra.
  • •Cài đặt SEO của từng trang nay được dùng thực sự, và khi cùng một nội dung xem được qua nhiều địa chỉ thì sẽ xác định địa chỉ chính (canonical).
  • •Đã thêm ô mã xác minh trang web Bing. Tìm kiếm của ChatGPT dùng chỉ mục của Bing.
  • •Phần mô tả được cắt theo độ rộng hiển thị của kết quả tìm kiếm, cắt ở cuối câu chứ không phải giữa câu.

Chỉnh lại việc hiển thị ngôn ngữ

  • •Màn hình 404 trước đây luôn hiển thị bằng tiếng Hàn. Nay hiển thị theo ngôn ngữ đang xem (tiếng Nhật, tiếng Hàn hoặc tiếng Anh; các ngôn ngữ khác dùng tiếng Anh).
  • •Đã sửa chữ "vừa xong" trên chuông thông báo vốn bị viết cố định bằng tiếng Hàn.
  • •Màn hình tiếng Nhật ưu tiên dùng phông chữ tiếng Nhật. Hàm hỗ trợ phông chữ theo ngôn ngữ luôn được nạp, nên các màn hình không đi qua bố cục (như trang chia sẻ) không còn bị dừng vì phông chữ.
  • •Danh sách "Ngôn ngữ ưu tiên" ở Trang của tôi không còn liệt kê cả những ngôn ngữ chưa có nội dung.
  • •Khi đăng ký thành viên, ngôn ngữ của màn hình đang xem được lưu làm ngôn ngữ ưu tiên (trước đây để trống). Email đặt lại mật khẩu cũng được gửi bằng ngôn ngữ đó.

Nhập liệu và đăng nhập

  • •Ngày tháng như ngày sinh nay được nhập bằng 3 ô: năm, tháng và ngày. Trước đây cách hiển thị thay đổi theo ngôn ngữ trình duyệt.
  • •Đã sửa lỗi bỏ sót bước xác minh reCAPTCHA khi đăng nhập và khôi phục mật khẩu ở một số giao diện.

Thanh toán

  • •Khóa thử nghiệm và khóa chính thức được lưu riêng cho từng cổng thanh toán. Chỉ cần chọn chế độ thử nghiệm, và khóa không còn bị mất khi chuyển đổi.

Widget

  • •Nút của widget hero nay có thể mở trong cửa sổ mới.
  • •Các mục lặp lại trong trình dựng widget cũng có thể viết theo từng ngôn ngữ (nút quả địa cầu).

Build

  • •Tệp cấu hình (.env) và bản sao lưu của nó không bao giờ được đưa vào bản phân phối, dù tên là gì.
  • •Các tệp sao lưu còn sót lại khi chỉnh sửa (.bak, kể cả tệp có ngày tháng phía sau tên) cũng không được đưa vào.
  • •Các script chỉ dùng cho vận hành của trụ sở (đồng bộ website, hosting, máy chủ thư, cập nhật điều khoản, v.v.) và các cron chỉ dùng cho plugin không có trong bản phân phối đã được loại khỏi bản phân phối. Những script mà website của khách hàng cần, như worker cập nhật, cài đặt và dịch, vẫn được giữ lại.
  • •Sau khi tạo tệp zip sẽ kiểm tra thêm một lần; nếu có tệp cấu hình hoặc tệp sao lưu bên trong thì dừng việc phát hành.
  • •Script dùng để kiểm thử không còn ghi mật khẩu trong tệp mà đọc từ cài đặt.
v2.7.10 2026-08-23 · 2 tháng trước
Tên phiên bản vẫn cũ sau khi cập nhật

Cập nhật rồi mà tên và ngày phát hành của phiên bản không đổi

Chỉ có số tăng lên, còn tiêu đề vẫn là của phiên bản trước.

Màn hình quản trị hiện kiểu «2.7.9 · Phông chữ tiếng Nhật · thông báo gia hạn hợp đồng…», số và tên không khớp nhau.

Chỉ nhìn màn hình thì không biết mình đã nhận được gì.

  • •Nguyên nhân: version.json là tệp cố ý không bị ghi đè, để bảo vệ cài đặt riêng của từng khách hàng.

Vì vậy trình cập nhật tự điền vào, nhưng nó chỉ thay số và thời điểm, còn tiêu đề và ngày phát hành thì để nguyên.

  • •Cách sửa: tiêu đề và ngày phát hành của phiên bản mới nay được đọc từ gói đã nhận và áp dụng cùng.

Với các bản cập nhật một phần không có gói, chúng được đọc từ danh sách phân phối (manifest.json).

Cài đặt riêng của từng khách hàng (github v.v.) được giữ nguyên.

Lưu ý — dù đã nâng lên phiên bản này, màn hình vẫn có thể hiện tên cũ. Vì người chạy cập nhật là

trình cập nhật của phiên bản đang được cài lúc này.

Từ phiên bản kế tiếp sau phiên bản đã nhận 2.7.10 trở đi, nó sẽ hiện đúng.

Kiểm tra build

Việc trình tạo bị đơ ở 2.7.8 (đã sửa ở 2.7.9) đã vượt qua bài kiểm thử hồi quy một cách nguyên vẹn.

Vì các kiểm tra hiện có chỉ xem «tệp có tồn tại không · chuỗi có nằm trong không».

  • •Nay đoạn mã đưa vào trình tạo được thực sự tạo ra và kiểm tra cú pháp (node --check).
  • •Nếu có mã nào đưa nguyên một tệp nhiều dòng vào chuỗi JS, build sẽ bị chặn kèm chỉ rõ số dòng.
  • •Chúng tôi đã thử bằng một tệp tái hiện 2.7.8 và xác nhận rằng bước kiểm tra thực sự chặn được nó.
v2.7.9 2026-08-23 · 2 tháng trước
Trình tạo widget bị đơ (hồi quy của 2.7.8)

Triệu chứng

  • •Không thấy một widget nào trong bảng chọn
  • •Các widget đã bố trí không được vẽ lên khung vẽ — video, hình ảnh v.v. đã đặt vào trông như biến mất
  • •Không lưu được

Nguyên nhân

Ở 2.7.8, chúng tôi gom phần khai báo phông chữ về một nơi là partials/fonts.php. Nhưng chỗ tạo bản xem trước của trình tạo lại nằm

bên trong một dòng của chuỗi JS, và đoạn khai báo phông chữ dài 33 dòng đã được chèn vào nguyên xi.

Ngay khi dòng bị ngắt, chuỗi bị đứt và toàn bộ tập lệnh của trình tạo chết trước cả khi được đọc.

Vì đây là loại lỗi giết cả tệp, nó không giống «một vài chức năng lạ» mà giống như trình tạo chẳng làm gì cả.

Phiên bản 2.7.5 trở xuống không có vấn đề này.

Cách chúng tôi đã sửa

Chúng tôi giữ phần định nghĩa phông chữ ở đúng một nơi là fonts.php, và chỉ khi chèn vào trình tạo thì đầu ra mới được gập thành một dòng và xử lý dấu ngoặc kép.

Nơi để chỉnh phông chữ vẫn chỉ có một.

v2.7.8 2026-08-22 · 2 tháng trước
Phông chữ tiếng Nhật · thông báo gia hạn hợp đồng · 3-D Secure

Phông chữ mặc định lấy tiếng Nhật làm chuẩn

Cho đến nay phông chữ mặc định lấy tiếng Hàn làm chuẩn. Người dùng chính của chúng tôi ở Nhật, vậy mà màn hình trông gượng gạo,

và đổi ngôn ngữ thì phông chữ vẫn y nguyên, khiến câu tiếng Nhật bị in bằng phông chữ tiếng Hàn.

  • •Giá trị mặc định nay là Mincho cho tiêu đề và Pretendard JP cho nội dung.
  • •Ở màn hình cài đặt ngôn ngữ, bạn có thể chỉ định phông chữ riêng cho từng ngôn ngữ. Nếu không chỉ định, ngôn ngữ đó sẽ nhận giá trị mặc định phù hợp.
  • •Cùng một quy tắc áp dụng cho mọi màn hình quản trị, thành viên và giao diện phía trước, cũng như mọi giao diện (default, modern, minimal, shop).

Thông báo gia hạn hợp đồng và kết thúc thời gian miễn phí

Có trường hợp chúng ta chỉ biết hợp đồng hết hạn sau khi nó đã qua. Nay hệ thống báo trước khi ngày gia hạn đến gần.

  • •Lịch gia hạn sắp tới và việc kết thúc cung cấp miễn phí được hiện bằng thông báo trước khi đến ngày.
  • •Chạy bằng một dòng cron (cron.d-voscms-contract-notice), và hướng dẫn cài đặt đã có cách đăng ký.

Thanh toán thẻ

Các khoản thanh toán đã qua xác thực của công ty thẻ Nhật (3-D Secure) qua được xác thực nhưng khoản thu bị từ chối.

  • •PAY.jp chặn không cho dùng token được tạo để xác thực nếu cứ để nguyên như vậy. Sau khi qua xác thực, máy chủ phải thực hiện một lệnh gọi hoàn tất,

lúc đó token mới dùng được cho việc thu tiền, và đúng một bước đó đã bị thiếu.

  • •Chúng tôi cũng mở ra cách kiểm tra trước xem thông tin khách hàng còn ở phía công ty thanh toán hay không — ngăn lỗi do thử thu tiền bằng khách hàng đã bị xóa.

Chuông thông báo và quy định hoàn tiền theo nhiều ngôn ngữ

  • •Ở chuông thông báo trên header, những dòng như «Không có thông báo» và «phút trước» vốn bị đóng cứng bằng tiếng Hàn nay đổi theo từng ngôn ngữ.
  • •Chúng tôi đã dọn các cụm từ cố định còn sót lại trong thông báo quy định hoàn tiền.

Kế toán

Sổ sách của pháp nhân Nhật bị lẫn giao dịch bằng won, khiến tổng không khớp.

  • •Chứng từ có đơn vị tiền tệ khác với tiền tệ sổ sách (yên) không tạo bút toán. Bản ghi vẫn được giữ nhưng không đi vào sổ.

Dọn dẹp bản phân phối

  • •Tệp sao lưu sinh ra trong lúc chỉnh sửa bị đóng gói vào bản phân phối (có dạng tên_tệp.php.bak.số).

Quy tắc loại trừ chỉ lọc .bak nên bỏ sót những tên có gắn số. Nay chúng tôi chặn cả .bak., .orig và *~.

  • •Tài liệu bán hàng của dịch vụ THEVOS AI (bảng giá, tính gói, cron đối chiếu thanh toán) đã được gỡ khỏi bản phân phối.

Mọi nơi đọc chúng đều đã bị gỡ, nên trong bản phân phối đó là những tệp không ai dùng.

v2.7.7 2026-08-10 · 2 tháng trước
Hai cảnh báo hiện ra khi cài mới

«Cần migration DB»

039_ai_knowledge_base tạo các bảng cho AI tư vấn cửa hàng của NaitoWork X,

vậy mà nó được đưa nguyên vào bản phân phối. Hơn nữa, dòng cuối cùng của tệp này là

ALTER TABLE rzx_shop_inquiries ADD COLUMN IF NOT EXISTS ai_meta ...

rzx_shop_inquiries là bảng do plugin vos-store tạo ra.

Bản phân phối không có vos-store — phần lõi đã cố sửa bảng của một plugin không tồn tại.

Vì vậy ở mỗi bản cài mới: 4 bảng được tạo rồi thất bại ở dòng cuối → vì không chạy tới cuối,

nên không được ghi nhận là «đã áp dụng» → banner hiện vĩnh viễn, và bấm vào lại thất bại đúng chỗ cũ.

Chúng tôi đã loại tư vấn AI (RAG) khỏi bản phân phối hoàn toàn:

039 · rzxlib/Core/AI/{Knowledge,Embedding,Generate} ·

scripts/{ai-kb-ingest,ai-rag-test,cron-ai-consult,hanesbot-ingest}.php

Dịch bằng AI (rzxlib/Core/AI/Translation) vẫn được giữ lại. Đó là động cơ của plugin trả phí vos-ai
và tuân theo quy tắc giống kế toán và hosting: «động cơ nằm ở phần lõi, còn tính năng do plugin mở ra».

«1 plugin chưa được xác thực (vos

Phần lõi giữ một danh sách «plugin đi kèm dùng được mà không cần giấy phép», và danh sách đó đã cũ.

Mã nguồn tưởng là đi kèm | vos-autoinstall · vos-marketplace |

Thực tế đi kèm | vos-autoinstall · vos-community |

vos-marketplace đã rời khỏi bản phân phối và vos-community vào thế chỗ,

nhưng chỉ có danh sách này là không được sửa. Chúng tôi đã đi kèm nó rồi lại đưa ra cảnh báo vì không biết nó là đi kèm.

Để chuyện này không lặp lại

Nguyên nhân là danh sách đi kèm được viết ở hai nơi —

danh sách loại trừ của tập lệnh build và LicenseStatus::BUNDLE_PLUGINS.

Chúng tôi đã thêm vào build một bước đối chiếu. Nếu hai nơi lệch nhau thì không tạo zip và dừng lại.

Đây không phải việc con người phải nhớ.

v2.7.6 2026-08-10 · 2 tháng trước
Nút viết bài bảng tin · Tiêu đề đa ngôn ngữ · Migration khi cài đặt

Nút viết bài không hiện trên bảng tin

Ở Q&A·FAQ, ngay cả người có quyền viết cũng không thấy nút. Nguyên nhân có hai hướng.

  • •Quản trị viên bị chặn — khi xét quyền viết, hệ thống kiểm tra có phải thành viên trước rồi mới xét quản trị viên.

Quản trị viên không có trong users nên bị chặn ngay ở cửa đầu tiên. Đã đổi thứ tự để quản trị viên được cho qua trước.

  • •Không có bài nào thì nút cũng biến mất theo — vì nút nằm bên trong danh sách,

khi chuyển sang màn hình "không có bài viết" thì nút cũng mất theo. Người viết đầu tiên không viết được.

Đã đưa nút ra ngoài danh sách.

  • •FAQ thậm chí xem trực tiếp admin_id — bỏ qua quyền viết trong cài đặt bảng tin.

Tiêu đề·phụ đề bảng tin hiển thị bằng ngôn ngữ khác

Lỗi màn hình tiếng Hàn nhưng riêng phụ đề lại hiện tiếng Nhật.

  • •Hoàn toàn không đọc bản dịch. Tiêu đề·phụ đề được lưu trong cài đặt giao diện dưới dạng một chuỗi duy nhất,

còn bản dịch nằm riêng ở rzx_translations. Màn hình chỉ in nguyên chuỗi đã lưu.

  • •Không phân biệt bảng tin. Khóa dịch là skin_config.subtitle_text nên Q&A và FAQ

dùng chung một ô. Sửa bên này thì bên kia cũng đổi theo.

Đã tách thành board.{board_no}.{item}.

  • •Phần thân được vẽ trước khi xác định ngôn ngữ. Lõi tạo phần thân trước rồi mới gắn phần đầu,

nhưng ngôn ngữ lại được xác định ở phần đầu. Đã chuyển sang xác định trước ở phía phần thân.

Khi cài đặt bị thiếu migration của lõi

install-core.php hoàn toàn không xem database/migrations.

Website mới cài thiếu vài bảng ngay từ đầu, và khi bật tính năng đó sau này thì mới bị lỗi.

Lỗi migration bị bỏ qua âm thầm (tiếp theo 2.7.4)

Ở 2.7.4 đã xử lý chú thích một dòng (--), nhưng chú thích nhiều dòng (/ /) vẫn còn.

Do dấu chấm phẩy trong khối đó, cả tệp bị gộp thành một khối, không dòng nào được chạy

mà vẫn được ghi là «đã áp dụng». Đã xác nhận thiệt hại thực tế — có bản cài đặt mất trọn 9 bảng.

-- hay /* nằm trong chuỗi ký tự không phải là chú thích. Đã xóa trong khi đếm dấu nháy.

Khác

  • •Header cửa hàng — thêm «Tất cả danh mục» vào đầu menu thả xuống danh mục.

Người muốn vào xem không có chỗ nào để đi.

  • •Trình dựng widget — tách phần chỉnh sửa mục lặp lại (repeater) ra tệp riêng.
  • •Thanh bên intranet — tìm chuỗi kế toán ở cả ba loại (salon·cửa hàng trực tuyến·doanh nghiệp thông thường).

Vì chỉ xem một loại nên khi dùng kế toán loại khác, menu hiện nguyên khóa thô.

  • •Trang của tôi — sắp xếp lại bảng điều khiển.
  • •Báo cáo plugin trả phí — gửi kèm các plugin trả phí đang bật trong lần kiểm tra giấy phép.

Plugin chỉ cài mà không bật thì không gửi — chi phí chỉ tính cho plugin đã bật.

v2.7.5 2026-08-05 · 3 tháng trước
Gỡ các trang hệ thống chỉ dành cho trụ sở khỏi bản phân phối

Các trang chỉ dành cho trụ sở đã bị đưa ra trong bản phân phối

config/system-pages.php bị đưa nguyên vào bản phân phối, khiến "Trang hệ thống" trong quản trị của bản cài của khách hàng

có sáu menu bấm được nhưng bên trong không có gì.

Đã gỡLý do

📥 downloads | Tải bản phân phối — chỉ trụ sở phát hành |

📋 changelog | Đó là lịch sử sản phẩm của trụ sở |

📧 contact | Khách hàng tự làm bằng widget (nó không phải trang hệ thống) |

💼 recruit · 💃 casts | Chỉ dành cho cổng thông tin kinh doanh ban đêm (NaitoWork X) |

🎟 coupons | Do plugin của chợ cung cấp |

  • •Đã thêm bước build [4e/8] (strip-system-pages.php). Sau khi xóa, cú pháp được kiểm tra bằng php -l —

nếu tệp này hỏng thì toàn bộ màn hình quản trị sẽ chết.

  • •Các trang hệ thống còn lại trong bản phân phối là tám trang: home · terms · privacy · data-policy ·

refund-policy · hosting-terms · tokushoho · funds-settlement

Trang hệ thống của plugin

  • •Đã thêm văn bản site.pages.blog vào 13 ngôn ngữ.

Ngay cả khi plugin đăng ký một trang hệ thống, nếu lõi không có văn bản cho nó thì site.pages.blog sẽ hiện nguyên như vậy trên màn hình.

  • •(Bản sửa plugin.json riêng của vos-blog được phát hành qua chợ — đó là plugin không nằm trong bản phân phối)

Các trang web đã cài đặt

Nếu "Trang hệ thống" trong quản trị hiện ra mục bạn không dùng, hãy xóa khối tương ứng khỏi config/system-pages.php.

Nội dung trang (rzx_page_contents) không bị xóa — nó chỉ biến mất khỏi danh sách.

v2.7.4 2026-08-05 · 3 tháng trước
Các migration bị bỏ qua một cách âm thầm

① Các migration bắt đầu bằng chú thích bị bỏ qua toàn bộ

  • •Một chú thích trong DatabaseMigrator::splitSql() ghi "tách sau khi loại bỏ chú thích", nhưng

thực tế nó chỉ tách theo dấu chấm phẩy.

  • •Nếu dòng đầu của tệp SQL là -- mô tả, toàn bộ tệp trở thành một đoạn duy nhất,

bị chặn lại bởi str_starts_with($stmt, '--') ở phần thực thi, và không có câu lệnh nào được chạy.

  • •Khi chạy 0 câu lệnh thì lỗi cũng là 0, nên nó được coi là success và được ghi nhận là đã áp dụng.

Một khi đã ghi nhận thì không chạy lại nữa, nên bảng cứ thiếu mãi mãi.

  • •Phạm vi thiệt hại gồm mọi tệp bắt đầu bằng --. Đo đạc: trong 9 tệp, 6 tệp chạy 0 câu lệnh và 2 tệp chạy một phần.
  • •Nay nó loại bỏ chú thích dòng -- và # cùng các khối / / trước khi tách.

-- nằm trong chuỗi thì không bị đụng đến (nếu một giá trị như 'a -- b' bị cắt thì dữ liệu sẽ hỏng).

② Cài đặt mới hoàn toàn không chạy các migration tăng dần

  • •Tập lệnh cài đặt chỉ chạy migrations/core và migrations/migrations

và bỏ sót cấp trên cùng database/migrations/*.sql. Ngược lại, trình cập nhật chỉ theo dõi cấp trên cùng.

  • •Vì vậy khi cài mới, 034 đến 042 không có ngay từ đầu và cứ trống cho đến khi bản phát hành tiếp theo đến.
  • •Khi cài đặt, nay cấp trên cùng cũng được chạy và được ghi nhận là đã áp dụng (để lần cập nhật đầu tiên không chạy lại chính những cái đó).

Các trang web đã cài đặt

Vui lòng nhấn Chạy migration một lần trong Quản trị → Cài đặt → Cập nhật.

Những mục bị ghi nhận sai sẽ không chạy lại, nên nếu một bảng trống, bạn có thể kiểm tra bằng cách sau.

SELECT migration FROM rzx_migrations;      -- đã ghi nhận
SHOW TABLES LIKE 'rzx_home_notices';       -- thực tế
v2.7.3 2026-08-05 · 3 tháng trước
Chỉnh đốn plugin của bản phân phối · header mua sắm · số dư ở Trang của tôi

Những gì được lấy ra khỏi bản phân phối

  • •vos-cp (bảng điều khiển dịch vụ) và vos-shopping (cửa hàng trực tuyến) đã đi kèm theo trong bản phân phối.

Cả hai đều là plugin mới làm và chỉ là chưa có trong danh sách loại trừ.

  • •vos-cp là bảng điều khiển dành cho các dịch vụ riêng của THEVOS. Không có lý do gì để nó nằm trong bản cài của khách hàng
  • •vos-shopping vẫn đang trong quá trình phát triển (v0.1.0), và nguyên tắc là plugin được mua từ chợ
  • •vos-review cũng được lấy ra — với cùng lý do (chỉ thị của chủ sở hữu).
  • •Plugin đi kèm trong bản phân phối chỉ có hai: vos-community và vos-autoinstall.

Tất cả những cái còn lại đều được lấy từ chợ.

Những gì được thêm vào lõi

  • •Header cửa hàng hai tầng (skins/layouts/shop) — menu thả xuống tất cả danh mục, tìm kiếm, xem trước giỏ hàng và

menu ảnh đại diện sau khi đăng nhập. Ở trên cùng của menu thả xuống danh mục, chúng tôi đặt "Tất cả danh mục" để có đường quay lại

  • •Điểm tích lũy, tiền tích lũy của cửa hàng và hạng thành viên được hiển thị ở Trang của tôi. Tên dùng đúng giá trị bạn đã đặt
  • •Hỗ trợ widget của plugin — nếu plugin có thư mục widgets/, trình tạo của lõi sẽ tự động nhận ra
  • •Thành phần dùng chung tìm kiếm địa chỉ bằng mã bưu chính — biểu mẫu đơn hàng và thông tin thành viên dùng cùng một thành phần
  • •Chuông thông báo trên thanh trên cùng của quản trị
  • •Chỉnh đốn các nhóm menu của bảng điều khiển quản trị (config/intranet-modules.php)
  • •Hỗ trợ trường lặp (repeater) của trình tạo widget

Những gì đã sửa

  • •Vấn đề các trường nhập đa ngôn ngữ ghi đè lên dữ liệu gốc
  • •Một lỗi trong việc ghi sổ cái tiền tích lũy của cửa hàng
  • •Vấn đề bản cập nhật của bản phân phối biến các trang hosting thành 404

Những điều cần kiểm tra trên các bản đã cài

Trên các trang web được cài bằng bản phân phối cũ và chỉ nhận các bản cập nhật, các thư mục plugin không dùng vẫn còn lại

(bản cập nhật không xóa thư mục plugin). Bất cứ mục nào hiển thị là chưa cài trong Quản trị → Plugin

đều có thể xóa khỏi plugins/ cùng với thư mục của nó.

v2.7.2 2026-07-26 · 3 tháng trước
Chỉnh đốn định tuyến đăng ký dịch vụ (xây dựng lại lõi)

Changed

  • •Định tuyến thống nhất cho các URL đăng ký dịch vụ — /service/hosting, /service/mail và /service/domain → đến /service/order bằng 302 (cho đến khi các trang đăng ký chuyên dụng sẵn sàng, khách truy cập được hướng dẫn đến trang đăng ký tích hợp, và sau này có thể thay bằng các trang chuyên dụng).

Notes

  • •Các bản sửa lõi của 2.7.1 (hreflang đa ngôn ngữ, ngăn thất bại âm thầm của trình cập nhật, gộp trang bảng giá /pricing vào /service/order) đã được đưa vào gói 2.7.1 một cách đúng đắn. 2.7.2 là bản xây dựng lại, thêm vào phía trên đó việc chỉnh đốn định tuyến đăng ký dịch vụ.
  • •Bản phân phối về nguyên tắc chỉ chứa lõi thuần túy (loại trừ plugin trả phí và plugin theo ngành dọc). Các trang web của trụ sở (voscms.com và thevos.jp) không phải đối tượng của việc tự cập nhật bản phân phối; chúng được triển khai từ mã nguồn/git.
v2.7.1 2026-07-25 · 3 tháng trước
SEO đa ngôn ngữ hreflang · ổn định trình cập nhật · chỉnh đốn bảng giá

SEO

  • •hreflang đa ngôn ngữ — canonical tự tham chiếu cho từng trang + hreflang tự động cho các ngôn ngữ được hỗ trợ, lập chỉ mục theo ngôn ngữ bằng ?lang=xx, chuẩn hóa 301 ?lang của ngôn ngữ mặc định về URL trơn và sitemap được mở rộng.

Fixed

  • •Sửa lỗi thất bại âm thầm của trình cập nhật — việc ghi tệp lõi hoặc version.json thất bại nay được xử lý như ngoại lệ. Khi việc áp dụng thất bại do thiếu quyền và các lý do tương tự, bạn nhận được lỗi rõ ràng cùng việc tự động khôi phục thay vì một "SUCCESS" sai.
  • •Ngăn chặn sự cố 500 trên trang bảng giá khi một trường đa ngôn ngữ bị truyền vào htmlspecialchars dưới dạng mảng.

Changed

  • •Mở rộng công tắc reCAPTCHA v3 theo từng biểu mẫu (blog_comment và các biểu mẫu khác).
  • •Tab "Thông báo bảng điều khiển chủ cửa hàng" trong cài đặt chỉ hiển thị khi vos-store đang bật.
  • •Trang bảng giá /pricing được gộp vào /service/order (301), và gói "Hệ thống không giới hạn" chỉ dành cho quản trị viên.
v2.7.0 2026-06-27 · 4 tháng trước
Bản phân phối được thu gọn thành lõi thuần túy + widget và cài đặt được tăng cường mạnh mẽ

Thành phần của bản phân phối

  • •Bản phân phối được thu gọn thành lõi thuần túy — chỉ kèm 3 plugin lõi (vos-autoinstall, vos-community, vos-review). Các plugin theo ngành dọc (kinh doanh ban đêm / salon / POS), widget và giao diện (story) đều bị loại hoàn toàn. Các tính năng đa dụng như xác minh độ tuổi và banner cookie thuộc về lõi (rzxlib) nên được đưa vào.

Added/Changed (widget lõi)

  • •location-map — hỗ trợ nhúng không cần khóa (map_embed), loại bỏ sự phụ thuộc vào khóa API, và liên kết ngôn ngữ bản đồ với locale
  • •practice-tabs (tab lĩnh vực hoạt động) — một widget đi kèm mới
  • •Cài đặt độ rộng trang toàn cục (widget_page_width) — thống nhất độ rộng của các trang widget/tài liệu
Các widget dành riêng cho từng trang web không đi kèm (bundled:false) (hero-slideshow, overlap-cards, office-intro, page-hero, content-head, consult-cta, board-grid, clients-logos, giao diện hồ sơ của diễn đàn) không nằm trong bản phân phối lõi.

Removed

  • •Các widget trả trước (prepaid-charge, prepaid-pass, prepaid-purchase) — bị loại khỏi bản phân phối vì vos-prepaid không đi kèm

Added (cài đặt và lõi)

  • •Cổng xác minh độ tuổi được nâng lên thành cài đặt chung của lõi
  • •Điều chỉnh độ trong suốt nền của banner đồng ý cookie
  • •Hình ảnh logo theo từng ngôn ngữ
  • •Thông tin tài khoản ngân hàng trong thông tin doanh nghiệp + thông báo chuyển khoản ngân hàng
  • •Thông báo "Thẻ được chấp nhận" trên màn hình thanh toán (biểu tượng thương hiệu) + cài đặt của quản trị viên

Fixed

  • •Địa phương hóa tiêu đề và phụ đề trang theo ngôn ngữ của người truy cập (page-scoped db_trans), và sửa lỗi content_width không được áp dụng
  • •Sửa nhiều lỗi ở widget/quản trị/trang và bổ sung 13 ngôn ngữ
v2.6.24 2026-06-02 · 5 tháng trước
Tự động dọn dẹp orphan (tệp nguồn đã xóa) khi cập nhật

Added

  • •Tự động dọn dẹp các tệp obsolete — bản cập nhật ghi đè bằng zip gói đầy đủ không thể xóa các tệp đã bị loại khỏi nguồn, nên phần còn sót (orphan) vẫn nằm lại trong các bản đã cài (ví dụ settings.php nguyên khối đã bị tách và xóa trong một lần tái cấu trúc vẫn còn trong các bản cài cũ). Chúng tôi đã thêm một cơ chế dựa trên danh sách tường minh để dọn dẹp chúng.
  • •config/obsolete-files.php — danh sách tích lũy các đường dẫn cần xóa (các bản cài bỏ qua nhiều phiên bản cũng được dọn một lượt).
  • •Ngay sau applyUpdate() của trình cập nhật, cleanupObsoleteFiles() thực hiện unlink an toàn các tệp trong danh sách. Nó không bao giờ chạm vào các đối tượng được bảo lưu (.env, storage, v.v.), việc thoát khỏi đường dẫn và các thư mục.
  • •Đăng ký đầu tiên: resources/views/admin/settings.php.
v2.6.23 2026-06-02 · 5 tháng trước
Chỉnh liên kết 'Cài đặt hệ thống' trên bảng điều khiển

Fixed

  • •Liên kết 'Cài đặt hệ thống' trên bảng điều khiển — liên kết trong thao tác nhanh trỏ đến đường dẫn cũ /settings đã bị tách và xóa, nên dẫn đến một trang sai (dự phòng). Đã chỉnh sang điểm vào cài đặt /settings/general. (Bị sót sau bản build 2.6.22.)
v2.6.22 2026-06-02 · 5 tháng trước
Sửa lỗi CSRF và ghi nhận khi chạy migration

Fixed

  • •Banner 'Cần migration DB' trên bảng điều khiển — CSRF token invalid — nút thử lại không gửi token CSRF đến /update-api.php (run_migrations) nên bị từ chối với 419. Nay $_SESSION['csrf_token'] được đảm bảo tồn tại và được gửi ở cả header lẫn body.
  • •Banner không biến mất dù đã chạy migration — DatabaseMigrator::recordMigration giả định có cột batch và tiền tố patch_, nên trên lược đồ kiểu cài đặt (migration/version/executed_at) INSERT ghi nhận bị thất bại, và tiền tố còn làm việc khớp tên tệp bị lệch. Đã sửa để ghi nhận nguyên tên tệp, khớp với các cột thực tế. (Đây là nguyên nhân khiến khi cập nhật 2.6.20, migration chỉ để lại nhật ký "OK" mà không được áp dụng.)
v2.6.21 2026-06-02 · 5 tháng trước
Sửa lỗi lộ khóa lang thô trên đường dẫn của mô-đun intranet chưa cài đặt

Fixed

  • •Khóa thô trong thanh bên của các trang lõi như quản lý quyền quản trị viên — vì bố cục intranet được kích hoạt chỉ dựa vào route_prefixes trong config/intranet-modules.php, nên trang lõi /staff/admins trên trang web không có plugin tương ứng (ví dụ chưa cài vos-salon) được dựng với thanh bên intranet của salon, và các khóa salon.intranet., salon.section. bị lộ ra dưới dạng văn bản thô. Đã sửa.
  • •Thêm hàm trợ giúp dùng chung resolve_intranet_module() — chỉ kích hoạt intranet khi tài nguyên lang của mô-đun (plugin) thực sự đã được cài; nếu chưa cài thì quay về admin-sidebar của lõi.
  • •Logic phát hiện bị trùng lặp trong _head.php / admin-sidebar.php được hợp nhất vào hàm trợ giúp. Hành vi không đổi trên các trang web đã cài plugin (salon, store, v.v.).
v2.6.20 2026-06-02 · 5 tháng trước
Đồng bộ lược đồ điểm/hạng/nhóm (giải quyết lỗi lưu hạng)

Fixed

  • •Lỗi lưu hạng điểm — sửa lỗi thất bại với lỗi Unknown column 'group_id' khi lưu một hạng trong mô-đun điểm của quản trị viên. Nguyên nhân là xung đột lược đồ của point_levels/member_points giữa core/004 và migrations/019(v190) (CREATE TABLE IF NOT EXISTS trong 019 không thể thêm cột mới vào bảng đã có).
  • •migration 034_point_system_schema_reconcile (cấp trên cùng, tự động áp dụng khi cập nhật):
  • •point_levels — thêm group_id, đặt giá trị mặc định cho name và chỉ mục duy nhất cho level (để upsert hoạt động).
  • •member_points — thêm point/balance/total_accumulated/level.
  • •Tất cả đều additive (không mất dữ liệu), không ảnh hưởng đến các cột hiện có hay các bên sử dụng (như vos-prepaid).
v2.6.19 2026-06-01 · 5 tháng trước
3 widget mua trả trước + tên sản phẩm và hình ảnh đa ngôn ngữ + sửa chiều cao bảng màu của trình tạo widget

Added

  • •3 widget mua hàng — một widget tích hợp (prepaid-purchase, chọn mục hiển thị: tất cả / chỉ nạp tiền / chỉ vé lượt) + một widget chỉ nạp tiền (prepaid-charge) + một widget chỉ vé lượt (prepaid-pass). Một thành phần dùng chung purchase-widget.php chạy cả 3 widget (không trùng lặp), rẽ nhánh bằng bộ lọc $ppOnly.
  • •Hình nền sản phẩm — tải lên bằng kéo thả (cũng có thể nhấp để tải) trong modal thêm/sửa sản phẩm của quản trị viên, và hình nền được áp dụng ở Trang của tôi và thẻ widget. Migration 003 image_url.
  • •Nhập tên sản phẩm đa ngôn ngữ + dịch AI — dùng lại multilang-modal chung (nút quả địa cầu), lưu dựa trên rzx_translations và hiển thị bằng ngôn ngữ của người truy cập qua prepaid_name(). Dịch AI dùng lại điểm cuối /api/translations của lõi.
  • •Thêm ô nhập tên chủ thẻ vào biểu mẫu thanh toán (truyền cho createToken của PAY.jp).
  • •Chọn khách hàng khi nạp tiền thủ công — chuyển từ nhập trực tiếp user_id sang tìm kiếm có tự động hoàn thành theo tên/điện thoại/email (hành động customer_search). Danh sách tình trạng khách hàng cũng hiển thị tên + email của khách thay vì mã băm user_id.
  • •Công tắc kích hoạt — hộp kiểm kích hoạt sản phẩm được đổi thành công tắc.

Changed

  • •Hộp mua hàng 4 cột — lưới thẻ sản phẩm đáp ứng 2→3→4 (lg:grid-cols-4), và bỏ độ rộng cố định max-w-3xl của widget → khớp với độ rộng của vùng chứa nơi đặt.

Fixed

  • •Chiều cao bảng màu và mega menu của trình tạo widget — chiều cao hàng của trình tạo được cố định là calc(100vh - 88px), nhờ đó các danh mục bên trái và menu bung ra tự động chiếm toàn bộ chiều cao màn hình và hiện tượng chồng chéo các mục mega menu được giải quyết.
v2.6.18 2026-05-31 · 5 tháng trước
Xác thực URL trong biểu mẫu gửi thông báo + trải nghiệm nhập liệu thân thiện

Added

  • •Xác thực link trong api/broadcast.php — nếu thiếu giao thức, https:// được tự động thêm vào đầu (example.com → https://example.com); nếu không qua được filter_var FILTER_VALIDATE_URL, trả về 400 kèm lỗi field: 'link'; trên 500 ký tự thì bị từ chối.
  • •Xác thực theo thời gian thực ở phía máy khách — type="url", inputmode="url", và ngay khi nhập:
  • •Thiếu giao thức → viền emerald + ✓ + gợi ý "Sẽ được tự động bổ sung khi gửi: …"
  • •Máy chủ không có dấu chấm (.) hoặc định dạng hỏng → viền red + ⚠ + "Không phải định dạng URL hợp lệ"
  • •Bình thường → viền emerald + ✓ + "Đây là URL hợp lệ"
  • •Máy khách cũng bổ sung trước khi gửi → đảm bảo bản xem trước và nội dung thực sự được gửi trùng khớp.

Added

  • •Tiêu đề các phần: ✉ Soạn tin nhắn / 📡 Kênh gửi — nhóm hóa trực quan + văn bản giải thích.
  • •Bộ đếm ký tự (tiêu đề 0/255, nội dung 0/2000) — màu tự động: amber từ 70% trở lên, red từ 90% trở lên.
  • •Hộp xem trước tin nhắn (viền chấm) — hiển thị theo thời gian thực tiêu đề, nội dung và liên kết gộp lại sẽ trông thế nào trên LINE + bộ đếm tổng số ký tự n/5000 (red khi vượt 4500).
  • •Văn bản trợ giúp cho từng trường:
  • •Tiêu đề: "Được hiển thị đồng thời trong hộp tin nhắn của thành viên và thông báo LINE"
  • •Nội dung: "Nếu bạn viết URL trong nội dung, nó được tự động rút gọn + theo dõi lượt nhấp"
  • •Liên kết: "Được tự động thêm vào cuối nội dung sau một dòng trống. Nếu bạn cũng viết nó trong nội dung thì sẽ hiện hai lần, hãy lưu ý"
  • •Biểu tượng trạng thái ở bên phải ô nhập liên kết (absolute) — ✓ / ⚠ hiển thị ngay.

Added

🔗 Quy tắc xác thực URL (phần thứ 5 mới):

  • •Cần bắt đầu bằng http:// / https:// → được chuyển thành token theo dõi lượt nhấp
  • •Giao thức bị thiếu được tự động bổ sung
  • •Từ chối máy chủ không có dấu chấm hoặc có định dạng hỏng
  • •Giới hạn 500 ký tự
  • •Hộp ví dụ: ✓ https://voscms.com/event / ✓ example.com/page → tự động bổ sung / ✗ asdfasdf (máy chủ không có dấu chấm)

Notes

  • •Môi trường vận hành (voscms-com) và salon đã được đồng bộ. API, giao diện và i18n có hiệu lực ngay.
  • •i18n 13 ngôn ngữ: community.broadcast.guide_url_, section_message, section_channels*, subject_hint, body_hint, link_hint, link_{invalid,autofixed,valid}, preview_{title,empty}.
v2.6.17 2026-05-30 · 5 tháng trước
Hộp hướng dẫn gửi theo lịch ở bên phải trang gửi thông báo

Added

  • •Thay đổi bố cục /theadmin/community/broadcast — thẻ đơn trước đây được chia thành lg:grid-cols-3. Biểu mẫu gửi chính chiếm 2 cột bên trái (lg:col-span-2), và một hộp hướng dẫn mới chiếm 1 cột bên phải (<aside>, sticky top-4).
  • •Nội dung hướng dẫn gồm 6 phần:

1. 📅 Gửi theo lịch là gì? — tự động gửi vào thời điểm trong tương lai, dùng cho ban đêm, cuối tuần và sự kiện

2. 🛠 Cách sử dụng — 4 bước (chọn đối tượng → chọn LINE → chọn đặt lịch → gửi), giao diện có huy hiệu đánh số

3. ⏱ Độ chính xác của việc gửi — giải thích khoảng 5 phút của cron + một hộp ví dụ (10:00 → 10:00 đến 10:05)

4. 🆚 So sánh gửi ngay và gửi theo lịch — khác biệt về hành vi giữa hai chế độ dưới dạng thẻ

5. 📋 Kiểm tra hàng đợi — nút tắt dẫn đến /history?status=queued

6. ⚠ Lưu ý — phải sau ít nhất 30 giây trong tương lai, trong ứng dụng/push không thể đặt lịch, không hoạt động trên hosting không có cron, chưa hỗ trợ hủy từ giao diện

  • •Nền chuyển sắc chàm (from-indigo-50 to-blue-50) — hộp hướng dẫn khác biệt về mặt thị giác với thẻ chính nhưng vẫn hòa hợp nhẹ nhàng.
  • •i18n 13 ngôn ngữ — khoảng 20 khóa community.broadcast.guide_* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
v2.6.16 2026-05-30 · 5 tháng trước
Giao diện cài đặt locale ở Trang của tôi + thẻ tổng hợp lịch sử gửi (CTR/variant/locale)

Added

  • •Thêm thẻ "Ngôn ngữ ưa thích" vào /mypage/settings — một select với 14 tùy chọn (tự động / 13 ngôn ngữ). Khi lưu sẽ UPDATE rzx_users.locale và áp dụng ngay $_SESSION['locale'].
  • •Hook Auth::loginUser — khi đăng nhập, nếu có $user['locale'] và locale của phiên đang trống thì tự động điền vào. Nếu người dùng đã đổi thủ công trong phiên thì giá trị đó được ưu tiên giữ lại.
  • •i18n 13 ngôn ngữ — auth.settings.language.{title,description,label,auto,hint,save,success,error_invalid,error_save} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
  • •Sau khi thay đổi, giao diện hiển thị theo ngôn ngữ của thành viên từ trang kế tiếp, và nếu quản trị viên đã đặt messages_by_locale cho quy tắc gửi tự động thì nội dung khớp sẽ được gửi qua LINE cho thành viên đó.

Added

3 thẻ mới ở phần trên của /theadmin/community/broadcast/history (sau 4 thẻ hiện có):

1. Tỷ lệ nhấp tổng thể (CTR) — SUM(rzx_broadcast_clicks.click_count) / SUM(rzx_line_broadcasts.recipient_count WHERE status='sent') × 100. Chữ lớn màu emerald.

2. Kiểm thử A/B (30 ngày gần nhất) — với các lần gửi có variant IS NOT NULL, tổng hợp người nhận, lượt nhấp và CTR theo từng variant. Variant có CTR cao hơn được nhấn mạnh bằng emerald.

3. Phân bố theo locale (30 ngày gần nhất) — chỉ với các lần gửi có source='auto_rule' AND messages_by_locale IS NOT NULL, locale được khớp bằng cách so sánh các khóa của JSON messages_by_locale trong quy tắc với 30 ký tự đầu của nội dung broadcast → người nhận/lượt nhấp/CTR theo từng locale. Sắp xếp bằng ksort.

  • •i18n 13 ngôn ngữ: community.broadcast.stat_{ctr_title,ctr_breakdown,variant_title,variant_hint,locale_title,locale_hint,empty}.

Notes

  • •Cây thư mục voscms-com và salon đã được đồng bộ. Không có cột DB mới (tất cả đã nằm trong migration 008/009/010 của Step 4).
  • •Logic khớp locale so sánh 30 ký tự đầu của nội dung — nếu nội dung sau khi thay thế biến khớp nhau thì được tính vào cùng một nhóm locale. Nếu nội dung quá ngắn hoặc được điền đầy hoàn toàn bằng việc thay thế biến thì tỷ lệ khớp có thể giảm (trong tương lai có thể thêm trực tiếp cột locale vào dòng broadcast).
v2.6.15 2026-05-30 · 5 tháng trước
Định tuyến đa ngôn ngữ (Step 4-C) + hoàn tất 4 giai đoạn gửi tự động qua LINE

Added

  • •migration 010 — rzx_auto_broadcast_rules.messages_by_locale JSON NULL + rzx_users.locale VARCHAR(10) NULL + chỉ mục idx_locale.
  • •AutoBroadcaster::lineUserIdsWithLocale — tra cứu cặp userId LINE và locale của thành viên. Môi trường không có cột users.locale sẽ quay về lineUserIds.
  • •AutoBroadcaster::pickLocaleMessage — thứ tự ưu tiên: user.locale của thành viên → locale mặc định của trang web (rzx_settings.locale) → khóa đầu tiên của JSON (nếu tất cả đều trượt thì null → quay về nội dung A).
  • •AutoBroadcaster::fire — nếu có messages_by_locale thì dùng nội dung khớp với locale của từng thành viên; nếu không thì dùng variant A/B; nếu cũng không có thì dùng A đơn. Khi locale, variant và mặc định cho cùng một nội dung thì chúng được gửi như một nhóm bằng multicast (hiệu quả).
  • •Modal quy tắc của quản trị viên — "Bật định tuyến đa ngôn ngữ" và ô nhập JSON trực tiếp, mở rộng bằng <details>. Hiển thị bằng pretty-print. Xác thực invalid_locale_json.
  • •i18n 13 ngôn ngữ — community.automation.locale_{toggle,placeholder,hint} + fields.messages_by_locale + error.invalid_locale_json (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Notes

  • •Các bước 1 đến 4 của hạ tầng gửi LINE đã hoàn tất (2.6.9 đến 2.6.15):

1. Step 1 — CTA · utility stack · gửi thủ công · audience theo hạng · chọn nhiều (7872c4b, 7c94a55, c4a3325)

2. Step 2 — Tự động phân loại nhóm thành viên (b24979c)

3. Step 3 — Quy tắc gửi tự động theo sự kiện (60d47cd) + cron gửi theo lịch (8cf02ad)

4. Step 4 — Theo dõi lượt nhấp (79c99a84) + kiểm thử A/B (86e19b0b) + định tuyến đa ngôn ngữ (lần này)

  • •Migration 010 đã được áp dụng lên môi trường vận hành (voscms.com). users.locale là cột mới — mọi thành viên hiện có đều là NULL (dùng locale mặc định của trang web → hành vi giống như trước).
  • •Giao diện Trang của tôi để thành viên tự đặt locale ưa thích là cột mốc tiếp theo.
  • •Các đăng ký cron được khuyến nghị: /5 /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php, 0 3 /usr/bin/php8.3 /var/www/voscms-com/scripts/recalculate-member-grades.php.
v2.6.14 2026-05-30 · 5 tháng trước
Kiểm thử A/B (Step 4-B)

Added

  • •migration 009 — rzx_auto_broadcast_rules.message_template_b TEXT NULL, rzx_line_broadcasts.variant CHAR(1) NULL, rzx_broadcast_clicks.variant CHAR(1) NULL + chỉ mục (source_rule_id, variant).
  • •AutoBroadcaster::fire — nếu message_template_b không trống, các userId LINE được chia 50:50 thành A/B bằng crc32 mod 2. Với từng variant, lịch sử gửi được INSERT trước (logQueued) → wrap token → multicast → finalize. Cùng một người dùng luôn nhận cùng một variant khi gửi lặp lại (tính nhất quán của băm).
  • •Modal quy tắc của quản trị viên — tùy chọn "Bật kiểm thử A/B" và ô nhập variant B, mở rộng bằng <details>. Mặc định là gửi đơn giản một lần, còn A/B là lựa chọn bật rõ ràng.
  • •ClickTracker — truyền siêu dữ liệu variant. Nếu có cột broadcast_clicks.variant thì được điền khi INSERT. Nếu không có thì dùng phương án dự phòng (tương thích với môi trường chưa áp dụng migration 009).
  • •Phương án dự phòng của logQueued — hoạt động cả trong môi trường không có cột variant (khi chưa áp dụng migration 009).
  • •i18n 13 ngôn ngữ — community.automation.ab_{toggle,placeholder,hint} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Notes

  • •Ba câu lệnh ALTER của migration 009 đã được chạy riêng rẽ trên môi trường vận hành (voscms.com). Các quy tắc hiện có có message_template_b=NULL (giữ nguyên hành vi gửi đơn).
  • •Chỉnh sửa quy tắc → nhập variant B trong phần mở rộng "Bật kiểm thử A/B" → chỉ cần lưu, từ lần phát sinh tiếp theo việc chia A/B diễn ra tự động.
v2.6.13 2026-05-30 · 5 tháng trước
Theo dõi lượt nhấp URL trong tin nhắn đã gửi (Step 4-A)

Added

  • •migration 008 (rzx_broadcast_clicks) — token (8 ký tự base62, UNIQUE), broadcast_id, source_rule_id, original_url (2048), click_count, last_clicked_at, last_user_agent. Cùng một tổ hợp (broadcast_id, original_url) sẽ dùng lại token.
  • •Lớp ClickTracker — wrap($pdo, $siteId, $body, $meta) trích xuất các URL http/https trong nội dung bằng biểu thức chính quy → INSERT hoặc dùng lại → thay bằng /t/{token}. consume($pdo, $token, $ua) chuyển token thành URL gốc và tăng click_count.
  • •Route /t/{token} (index.php:330) — đi vào bộ định tuyến biểu thức chính quy. ClickTracker::consume → chuyển hướng 302 tới URL gốc, nếu không có thì 404. Xác thực token URL ([A-Za-z0-9]{4,16}).
  • •Tích hợp với quy tắc gửi tự động — AutoBroadcaster::fire() hoạt động, ngay trước khi gửi, theo thứ tự logQueued → lấy broadcast_id → ClickTracker::wrap → multicast → finalizeBroadcast. Đảm bảo liên kết giữa token và broadcast_id.
  • •Tích hợp với gửi thủ công — trong api/broadcast.php, wrap ngay sau khi ghép xong văn bản gửi ngay. Trong scripts/process-scheduled-broadcasts.php, wrap ngay trước khi gửi từ hàng đợi (đã biết broadcast_id).
  • •Cài đặt tên miền theo dõi — ưu tiên rzx_settings.click_track_domain, nếu không có thì dùng APP_URL. Có thể dùng tên miền ngắn (ví dụ s.voscms.com).

Notes

  • •Migration 008 đã được áp dụng lên môi trường vận hành (voscms.com).
  • •Kiểm thử tích hợp wrap/consume: 2 URL trong nội dung → INSERT 2 token 8 ký tự → khi gọi consume, URL gốc được trả về và click_count tăng đúng.
v2.6.12 2026-05-30 · 5 tháng trước
Đặt lịch gửi LINE + xử lý hàng đợi bằng cron (Step 3-B)

Added

  • •migration 007 (rzx_line_broadcasts): các cột scheduled_at DATETIME NULL và processed_at DATETIME NULL cùng chỉ mục (status, scheduled_at). scheduled_at NULL = gửi ngay (như trước), thời điểm trong tương lai = vào hàng đợi.
  • •scripts/process-scheduled-broadcasts.php — điểm vào của cron. Lấy 50 mục có status='queued' AND scheduled_at <= NOW() AND processed_at IS NULL → khóa ngay bằng processed_at = NOW() (giao dịch) → phân giải audience (all / grade_N, giống broadcast.php) → LineMessenger multicast theo đơn vị 500 → cập nhật status theo kết quả. Chu kỳ cron khuyến nghị: /5 *.
  • •Giao diện broadcast.php: hộp kiểm [Đặt lịch gửi] + ô nhập datetime-local. Khi chọn, giá trị mặc định là thời điểm hiện tại + 1 giờ (giờ địa phương của người dùng). Nếu không chọn hoặc để trống thì gửi ngay như trước. Chỉ kênh LINE mới đặt lịch được (trong ứng dụng và push vẫn gửi ngay).
  • •api/broadcast.php: xử lý tham số POST scheduled_at. Với thời điểm trong tương lai (> NOW + 30s) và send_line, chỉ INSERT rzx_line_broadcasts (status='queued', scheduled_at) mà không gọi API LINE, rồi trả về scheduled: true, scheduled_at trong phản hồi.
  • •i18n 13 ngôn ngữ: community.broadcast.schedule_{label,enable,hint,success} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Fixed

  • •Đã sửa các cột của INSERT cho khớp với lược đồ thực tế của rzx_line_broadcasts (title, body, audience varchar(20), recipient_count, status enum(queued|sent|failed)). Trước đây INSERT dùng những tên cột không tồn tại (message_text, recipients_count, sent_count, failed_count, audience_value, partial), và ngay cả phương án dự phòng cũng thất bại nên lịch sử gửi tự động bị thiếu.

Notes

  • •Migration 007 đã được áp dụng lên môi trường vận hành (voscms.com). Dry-run xác nhận pickup là 0 mục.
  • •Cây thư mục của môi trường vận hành (voscms-com) và salon đã được đồng bộ. Đã loại trừ .env.
  • •Việc đăng ký cron do phía vận hành hosting quyết định (nếu cần, /5 * /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php).
v2.6.11 2026-05-30 · 5 tháng trước
Quy tắc gửi tự động LINE dựa trên sự kiện (Step 3-A)

Added

  • •Bảng quy tắc gửi tự động (rzx_auto_broadcast_rules) — migration 005_auto_broadcast_rules.sql. Quy tắc được tách biệt theo site_id, với các cột trigger_type / trigger_filter (JSON) / audience (all|grade_X|custom) / message_template / is_enabled / fired_count / last_fired_at.
  • •Bộ điều phối AutoBroadcaster (rzxlib/Core/Notification/AutoBroadcaster.php) — điểm vào tĩnh AutoBroadcaster::fire($triggerType, $ctx). Khớp với các quy tắc đang bật → thay thế biến của mẫu ({{title}}, {{url}}, {{author}}, {{board_name}}, {{site_name}}) → phân giải audience (cùng logic với broadcast.php; với hạng is_default, thành viên NULL được tự động đưa vào) → tra cứu userId LINE qua rzx_user_social_accounts → multicast theo đơn vị 500 → ghi lịch sử vào rzx_line_broadcasts → cập nhật thống kê của quy tắc.
  • •Hook gửi tự động cho bài viết mới trên diễn đàn (api-posts.php:184) — ngay sau khi INSERT một bài viết (trừ bài riêng tư), gọi AutoBroadcaster::fire('board_post', [post_id, board_id, title, url, author, board_name]). Dù gửi thất bại, phản hồi của bài viết cũng không bị ảnh hưởng.
  • •Trang quản trị quản lý quy tắc (/theadmin/community/automation) — giao diện lưới thẻ. CRUD quy tắc + công tắc bật/tắt + huy hiệu màu theo từng trình kích hoạt (board_post=blue, review_created=amber, reservation_created=green). Trình kích hoạt / bộ lọc (JSON) / hạng mục tiêu / mẫu tin nhắn được chỉnh sửa trong modal.
  • •Các cột theo dõi nguồn gốc của rzx_line_broadcasts — migration 006_line_broadcasts_add_source.sql. source ('manual' | 'auto_rule') + source_rule_id (INT) + một chỉ mục. Lịch sử gửi tự động có thể phân biệt với gửi thủ công trong cùng một bảng.
  • •Đăng ký route và migration trong plugin.json — route community/automation, và các migration 004/005/006 được nêu rõ sau 003.
  • •i18n 13 ngôn ngữ — tất cả các khóa community.automation.* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW). Nhãn trình kích hoạt, trường, gợi ý, thông báo thành công/lỗi và mẫu mặc định.

Notes

  • •Các migration 005/006 đã được áp dụng lên môi trường vận hành (voscms.com). Chưa đăng ký quy tắc nào.
  • •Cây thư mục của môi trường vận hành (voscms-com) và salon đã được đồng bộ. Đã loại trừ .env.
  • •Step 3-B (gửi theo lịch scheduled_at + cron) là cột mốc tiếp theo.
v2.6.10 2026-05-30 · 5 tháng trước
Tự động phân loại hạng thành viên + hạng mặc định khi đăng ký + nút tính lại của quản trị viên

Added

  • •Tự động gán hạng mặc định khi đăng ký (rzxlib/Core/Auth/Auth.php::register()) — ngay sau khi đăng ký thành viên, hệ thống tra cứu hạng có is_default=1 trong rzx_member_grades và điền ngay grade_id của thành viên mới. Với các trang web không có bảng member_grades (cũ hoặc chưa cấu hình), nó âm thầm bỏ qua bằng try-catch. Các thành viên NULL hiện có được điền bằng tập lệnh tính lại hoặc nút riêng.
  • •Tập lệnh CLI tính lại hạng (scripts/recalculate-member-grades.php) — dựa trên tổng số tiền thanh toán trong rzx_payments cộng số lượt đặt chỗ trong rzx_reservations (chỉ khi bảng tồn tại), duyệt các hạng theo thứ tự sort_order DESC và khớp với hạng cao nhất có thể đáp ứng. Hạng chưa đặt quy tắc (min_spent=0 AND min_reservations=0) tự động bị bỏ qua — chỉ các hạng có quy tắc rõ ràng mới là ứng viên thăng hạng. Thành viên không đủ điều kiện quay về hạng mặc định.
  • •Tùy chọn: --dry-run (mô phỏng, không UPDATE thật), --user-id=UUID (chỉ một thành viên cụ thể).
  • •Ví dụ cron: 0 3 * /usr/bin/php8.3 /var/www/voscms/scripts/recalculate-member-grades.php
  • •Nút "Tính lại ngay" của quản trị viên (/theadmin/members/groups) — thêm một nút tông xanh ngọc vào thanh tác vụ. Khi nhấp: modal xác nhận → AJAX action=recalculate_grades → thông báo kết quả (đối tượng/thăng hạng/giáng hạng/mới) → tự động làm mới. Vì chứa cùng logic với tập lệnh ngay trong mã, nút hoạt động cả trong môi trường không có quyền PHP CLI.
  • •i18n 13 ngôn ngữ — các khóa mới members.groups.recalculate* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW): recalculate, recalculate_hint, confirm_recalculate, recalculate_stat.{total,upgraded,downgraded,fallback}, success.recalculated, error.{no_grades,no_default_grade}.

Notes

  • •Trên môi trường vận hành (voscms.com), đã xác minh --dry-run → chạy thật → chạy lại sau khi bổ sung quy tắc. Cả 5 thành viên có grade_id NULL đều được gán đúng vào Normal (mặc định). VIP/Gold/Silver chưa đặt quy tắc nên giữ 0 thành viên cho đến khi thêm quy tắc (có chủ ý).
  • •Cây thư mục của môi trường vận hành (voscms-com) và salon đã được đồng bộ. Đã loại trừ .env.
v2.6.9 2026-05-30 · 5 tháng trước
CTA thêm bạn LINE + Utility Stack tích hợp + gửi thông báo qua LINE

Added

  • •Thành phần CTA thêm bạn LINE dành cho thành viên (resources/views/components/line-friend-cta.php) — 5 variant (card / button / bar / side-tab / bubble) × 6 vị trí (bottom-right/bottom-left/bottom-center/top-right/middle-right/middle-left) × 3 kích cỡ, màu do người dùng chỉ định, độ trễ hiển thị và "ghi nhớ đã đóng" trong 24 giờ (localStorage).
  • •Giao diện cài đặt có thể thay đổi — phần mới "CTA thêm bạn LINE" ở cuối thẻ kênh LINE trong /theadmin/settings/message-api. Basic ID, công tắc bật, radio variant, chọn position, kích cỡ, bộ chọn màu và ô nhập delay.
  • •Tự động hiển thị ở 5 bố cục — tự động được include từ skins/layouts/{default,modern,minimal,modern-copy-260413}/footer.php. Ở các trang thanh toán, đăng ký dịch vụ và luồng cài đặt, nó tự động bị bỏ qua.

Added

  • •Thành phần mới resources/views/components/utility-floating-stack.php — mẫu thiết kế cameron_plugin của thevos.jp (stack vuông 80×80 ở mép phải + khoảng cách 1px + màu nhấn riêng cho từng biểu tượng). Vị trí, kích cỡ và màu do nhà vận hành điều chỉnh.
  • •Hai chế độ cùng tồn tại — utility_stack_mode = separate (mặc định, mỗi CTA riêng lẻ) / unified (PWA + LINE gộp lại hiển thị thành một stack). Ở chế độ tích hợp, việc tự động hiển thị 5 variant của CTA LINE bị vô hiệu hóa và các trình kích hoạt tự động của modal cài đặt PWA (banner setTimeout/DOMContentLoaded) cũng bị vô hiệu hóa; modal chỉ mở khi nhấp vào biểu tượng PWA trong stack.
  • •Mở rộng tự nhiên trong tương lai — với mẫu đăng ký mục (kênh Kakao, WhatsApp, đăng ký bản tin, công tắc chế độ tối, v.v.), các mục khác có thể gia nhập stack chỉ bằng cách thêm khóa cài đặt.
  • •Đảm bảo tự động xuống dòng — CSS nội tuyến word-break: break-all; overflow-wrap: anywhere; max-width: 72px vượt qua giới hạn chiều rộng của phần tử con flex Tailwind. Nhãn CJK cũng xuống dòng tự nhiên trong khung.
  • •i18n 13 ngôn ngữ — nhóm line_cta. (22 khóa) và nhóm utility_stack. (12 khóa) trong resources/lang/{13 locale}/messaging.php. Với tiếng Nhật và tiếng Trung, khoảng trắng ở ranh giới ngữ nghĩa (ví dụ "アプリとして インストール") đảm bảo vị trí xuống dòng tự nhiên.

Added

  • •LineMessenger::broadcast(messages) + broadcastText(text) — gửi hàng loạt đến tất cả bạn bè (tối đa 5 đối tượng tin nhắn; hạn mức gửi của LINE bị trừ theo số người nhận × số tin nhắn).
  • •LineMessenger::multicast(userIds[], messages) — gửi đến tối đa 500 userId được chỉ định (hạ tầng gửi theo nhóm).
  • •Bổ sung giao diện /theadmin/community/broadcast — thêm hộp kiểm "Gửi cả cho bạn bè LINE" (banner xanh lá). Độc lập với gửi push, tự động gửi cho bạn bè LINE bằng multicast/broadcast.
  • •Gửi theo hạng thành viên — rzx_member_grades được tải động và các tùy chọn radio theo từng hạng tự động hiển thị (chấm màu + slug + số đếm thời gian thực). Định dạng audience là grade_<id>.
  • •Thành viên có grade_id IS NULL được tự động đưa vào hạng is_default=1 — ngay cả trên các trang web không tự động gán hạng khi đăng ký, thành viên NULL vẫn được tính tự nhiên vào số đếm và việc gửi của hạng mặc định.
  • •Bảng lịch sử gửi rzx_line_broadcasts — tách biệt theo site_id, method (broadcast/multicast), audience, title/body, recipient_count, line_request_id, api_status/error, status. Khi gửi, dòng được INSERT tự động.
  • •Với audience=all chọn broadcast, còn lại chọn multicast, tự động — thu thập userId LINE của người dùng mục tiêu có user_social_accounts.line_friend=1 và gửi theo từng khối 500.
  • •Thống nhất chiều rộng — trong broadcast.php, max-w-3xl → max-w-7xl (khớp với các trang quản trị khác).
  • •i18n 13 ngôn ngữ — thêm các khóa send_line_label/desc và audience_grade_group.

Changed

  • •resources/views/admin/dashboard.php — chú thích đầu tệp, giá trị dự phòng của pageTitle và banner thông báo cập nhật RezlyX v... đều được sửa thành "VosCMS".
  • •resources/views/admin/partials/admin-topbar.php — sửa chú thích đầu tệp.

Fixed

  • •storage/.update_cache giữ bộ nhớ đệm cũ current: "2.6.4", nên ngay cả sau khi cập nhật lên v2.6.8, bảng điều khiển vẫn hiển thị banner "Có bản cập nhật mới" — sau khi xóa bộ nhớ đệm, nó được tính lại tự động ở yêu cầu kế tiếp.
  • •Các thay đổi tích lũy từ dev → vận hành chưa được đồng bộ — ngoài phiên này, nhiều tệp như install-core.php (bản vá các lỗi #1 đến #7) và version.json cũng chưa từng được đồng bộ lên môi trường vận hành. Đã đồng bộ dev lên môi trường vận hành một lượt bằng rsync (342 tệp thay đổi + 196 tệp mới, 6,3MB, không gồm dữ liệu người dùng, .env, storage/, uploads/, vendor/ và .git/).

Documentation

  • •docs/LINE_FRIEND_CTA_DESIGN_GUIDE.md — thêm Part 3 (triển khai thực tế Utility Floating Stack tích hợp), Part 4 (triển khai thực tế vận hành gửi ở Giai đoạn 1), Part 5 (kịch bản người dùng bên ngoài — phân tích giá trị của gửi chọn nhiều) và Part 6 (lộ trình Giai đoạn 2 đến 4). Từ khoảng 631 lên 920 dòng.

Regression Test

  • •Xác minh sự tồn tại của utility-floating-stack.php và 5 tệp partial variant của line-friend-cta.
  • •Xác minh sự tồn tại của các phương thức LineMessenger::broadcast/multicast.
  • •Xác minh sự tồn tại của tệp migration plugins/vos-community/migrations/004_line_broadcasts.sql.
  • •Xác minh sự tồn tại của các khóa messaging.utility_stack. + community.broadcast.send_line_ trong 13 ngôn ngữ.
  • •Tự động xác minh không còn dấu vết RezlyX trong dashboard.php / admin-topbar.php.
v2.6.8 2026-05-29 · 5 tháng trước
Hợp nhất giấy phép Marketplace + Bảng phát hiện cài đặt trái phép + Hiệu chỉnh thương hiệu

Fixed

  • •Hợp nhất bảng giấy phép vos-market — 6 file API truy vấn sai bảng {$pfx}vos_licenses, gây ra "Server error" 500 mỗi lần thanh toán. Tất cả xác minh giấy phép hiện được chuyển hướng đến master duy nhất vcs_licenses (do vos-license-server quản lý).
  • •Loại bỏ lỗ hổng bảo mật đăng ký master không xác minh trong sync.php — Mã trước đây UPSERT vào vos_licenses mà không xác minh vos_key, cho phép bất kỳ ai tự động đăng ký các khóa giấy phép tùy ý vào master qua một POST đơn giản. Theo dõi hiện được xử lý bởi rzx_mkt_sync_reports hiện có (per-item).
  • •migrations/007 ngừng sử dụng — Migration được thiết kế sai hiện là no-op (SELECT 1), lý do và lịch sử thay đổi trong nhận xét.

Added

  • •4 thẻ thống kê — Trang được theo dõi / Trang cần chú ý / Giấy phép đa tên miền / Không hoạt động 30+ ngày.
  • •Tab vi phạm (hiển thị cấp mục) — Xem thoáng qua widget trả phí nào được cài đặt mà không có giấy phép trên tên miền nào. Giá, phiên bản, vos_key và lần cuối thấy được hiển thị.
  • •Tab đa tên miền — Các trường hợp một khóa giấy phép duy nhất được báo cáo từ nhiều tên miền.
  • •Tab không hoạt động — Các trang không có tín hiệu đồng bộ trong 30+ ngày.
  • •Định nghĩa vi phạm tinh chỉnh — unknown_product và các mục miễn phí bị loại trừ. Chỉ có các mục trả phí của marketplace ở trạng thái không có giấy phép được tính là vi phạm.
  • •Danh sách trắng tên miền sở hữu — Các tên miền của nhà điều hành được lưu trữ dưới dạng mảng JSON trong settings.mkt_owner_domains tự động bị loại khỏi tổng đếm.
  • •i18n 13 ngôn ngữ — Thanh bên, thẻ, tab và văn bản trợ giúp đều được dịch chính xác.

Changed

  • •settings/system/updates — Thẻ phiên bản đã cài và phiên bản mới nhất được sửa thành "VosCMS vX.Y.Z".
  • •updates/ajax.php — Dự phòng tên DB và User-Agent được sửa.

Regression Test

  • •Tự động xác minh không có dư SQL vos_licenses trong 6 file vos-market
  • •Phát hiện hồi quy lỗ hổng bảo mật INSERT trong sync.php
  • •Xác minh trạng thái no-op migrations/007 được duy trì
  • •Tự động xác minh không có dư RezlyX trong 3 file màn hình cập nhật
v2.6.7 2026-05-29 · 5 tháng trước
Trình hướng dẫn install an toàn hơn và đưa vào kiểm thử hồi quy tự động

Fixed

  • •Tự động khởi tạo site_url — Trình hướng dẫn install chỉ ghi siteUrl do người dùng nhập vào APP_URL của .env mà không ghi vào rzx_settings.site_url trong DB, nên mọi tính năng của trang web mới cài phụ thuộc vào site_url (cài đặt tự động, SEO, liên kết trong email, v.v.) đều hỏng. Đã sửa bằng cách thêm site_url vào mảng $settings của install-core.php.
  • •Tự động đăng ký vào rzx_site_domains — Trình hướng dẫn install không tự thêm tên miền cài đặt hiện tại vào bảng site_domains, nên SiteRouter không nhận ra tên miền. Nay tên miền đã cài được tự động INSERT làm primary của site_id=1.
  • •Tự động ghi MARKET_API_URL trong .env — Khi cài mới, .env không có địa chỉ API của chợ nên InstallerService không tìm được nơi để gọi. Nay giá trị mặc định https://market.voscms.com/api/market được ghi tự động (vận hành với một bản gốc giấy phép duy nhất).
  • •Lỗi chính tả tên bảng của API install chợ — vos-market/views/api/item/install.php truy vấn bảng không tồn tại rzx_vos_licenses khi xác minh giấy phép, khiến mọi cài đặt tự động trả về "Server error" (HTTP 500). Đã sửa sang bảng thật vcs_licenses (bản gốc giấy phép, cố định và không có tiền tố).
  • •Tự động đặt quyền cho các thư mục widgets/plugins/themes — Sau khi install, người dùng PHP-FPM không ghi được vào các thư mục này nên cài đặt tự động thất bại trong im lặng. Trình hướng dẫn install nay tự động cấp setgid và quyền ghi cho nhóm (tự động phát hiện nhóm chạy PHP để thích ứng với nhiều môi trường bên ngoài).
  • •Nhiều phương án dự phòng trong install-handler.php — Trong môi trường nhiều trang web, truy vấn site_url dùng LIMIT 1 mà không lọc theo site_id nên không ổn định. Phương án dự phòng ba bước gồm SiteRouter → quay về site_id=1 → $_SERVER['HTTP_HOST'] đảm bảo nhận diện được tên miền trong mọi môi trường.

Added

  • •InstallerService::installTheme() — Đọc theme.json của sản phẩm type=theme và cài đệ quy các plugin/widget/skin trong requires. Đảm bảo kiểm tra 13 ngôn ngữ và tính lũy đẳng (mục đã cài sẽ được bỏ qua).
  • •runPostInstall — Ngay sau khi cài giao diện, tự động chạy các seed post_install/settings.json / boards.json / pages.json, thiết lập trọn bộ trang + bố trí widget + cài đặt mặc định chỉ trong một lần.
  • •Bắt buộc 13 ngôn ngữ (REQUIRED_LOCALES) — Các đối tượng đa ngôn ngữ (name, description, title của trang, config.title của widget, v.v.) chỉ được thông qua chính thức khi có đủ 13 khóa. Sẽ cảnh báo với locale bị thiếu.
  • •Thống nhất bản gốc vcs_licenses — Mọi việc cấp và xác minh giấy phép đều được quản lý thông qua chợ vận hành chính thức (market.voscms.com). Môi trường dev/test cũng dùng cùng bản gốc.

Added

  • •Tự động xác minh sáu lỗi này — Tổng cộng 13 mục, gồm logic seed của trình hướng dẫn install, quyền thư mục, API chợ, khả năng truy cập máy chủ giấy phép, nhánh theme của InstallerService và các phương án dự phòng nhiều bước của install-handler.
  • •Hook tự động chạy trong build-voscms.sh — Được gọi tự động ở cuối build. Chỉ cần một FAIL, mã thoát sẽ khác 0 và việc phát hành bị chặn. Nếu cùng lỗi tái diễn ở lần build sau, nó sẽ bị bắt ngay.

Documentation

  • •docs/theme-package/THEME_PACKAGE_SPEC.md — Định nghĩa tiêu chuẩn gói giao diện của VosCMS (theme.json). Nêu rõ ví dụ giao diện tích hợp Salon, lược đồ chi tiết của post_install và quy tắc 13 ngôn ngữ.
v2.6.6 2026-05-27 · 5 tháng trước
Ngăn sao lưu cập nhật bị trùng

Fixed

  • •Sao lưu cập nhật: chỉ giữ một bản cho mỗi phiên bản — Backup::createFull() nay xóa bản sao lưu hiện có của cùng phiên bản trước khi tạo bản sao lưu mới. Điều này giải quyết vấn đề khi cập nhật hoặc khôi phục lặp lại trên cùng một phiên bản làm danh sách sao lưu chất đống các bản trùng của phiên bản đó (chỉ giữ trạng thái mới nhất ngay trước khi cập nhật).
v2.6.5 2026-05-27 · 5 tháng trước
Chỉnh đốn hệ thống cập nhật (một kênh, phiên/quyền, sửa bản phân phối)

Fixed

  • •Khôi phục update-api.php bị thiếu trong bản phân phối — Tập lệnh build phân loại nhầm update-api.php, phần backend của cập nhật, là "tệp dev" và xóa nó khỏi bản phân phối. Kết quả là tab cập nhật của mọi bản cài đặt từ bản phân phối đều không hoạt động và hiện "File not found". Tệp đã được gỡ khỏi danh sách loại trừ của build và nay được đưa vào bản phân phối đúng cách.
  • •Sửa lỗi không nhận diện phiên đăng nhập (Unauthorized) — update-api.php từng xem đường dẫn lưu phiên mặc định (/var/lib/php/sessions); nay dùng cùng storage/sessions như index.php. Điều này giải quyết lỗi Unauthorized xuất hiện ngay cả khi đã đăng nhập bằng quản trị viên.

Changed

  • •Cập nhật Core chỉ dùng manifest phân phối riêng làm kênh duy nhất — Đã xóa phần còn sót lại của thẻ GitHub, token và chẩn đoán trong update-api.php (chặn đường mà check ghi đè kết quả manifest bằng thẻ GitHub). Chợ ứng dụng không có Core (chỉ có plugin).
  • •Tăng cường bảo mật — Thêm xác minh CSRF và kiểm tra quyền chủ (master) vào update-api.php.
  • •Chỉnh đốn danh sách bảo lưu khi cập nhật — skins và config được loại khỏi danh sách bảo lưu. Vì applyUpdate chỉ sao chép, các giao diện lõi và config trong zip phân phối được cập nhật, còn tệp tùy chỉnh của khách hàng không có trong zip thì được giữ nguyên.

Changed

  • •Đã xóa nút "Kiểm tra cập nhật" bị trùng — phiên bản mới nhất được kiểm tra tự động khi vào trang.
  • •Sửa lỗi danh sách sao lưu biến mất khi gặp lỗi tạm thời → phần này được giữ lại và hiển thị ở trạng thái trống.
  • •Khi có lỗi, hiển thị thông báo "Hiện bạn đang dùng phiên bản mới nhất" thay cho các thông báo thô như Unauthorized.
v2.6.4 2026-05-26 · 5 tháng trước
i18n menu nhắc đến cộng đồng · Liên kết tác giả diễn đàn + cải tiến render & đa ngôn ngữ /changelog

Added

  • •Mục um 13 ngôn ngữ được thêm — tất cả locale của vos-community/lang/{locale}.php (ko·en·ja·de·es·fr·id·mn·ru·tr·vi·zh_CN·zh_TW): follow·following·message·block·unblock·report·report_about·report_reason/detail/placeholder·reason_spam/harassment/inappropriate/other·report_submit/sent/failed·msg_title/placeholder/send/sent/failed·block/unblock_confirm·block/unblock_done·cancel·failed·network_error
  • •i18n toàn diện cho user-mention-menu.php — toàn bộ tiếng Hàn hardcode trong HTML PHP được thay bằng __('community.um.*'); chuỗi runtime JS được phát ra dưới dạng đối tượng PHP qua UM_LANG = <?= json_encode(...) ?>, với hàm hỗ trợ umT(key, name) thay thế chỗ giữ :name
  • •Cho phép khách dùng menu nhắc đến — cải tổ cấu trúc bảo vệ trong community-overlays.php: chặn hoàn toàn đường dẫn admin/API, trong khi user-mention-menu được bao gồm cả với khách (theo dõi/báo cáo sẽ mời đăng nhập); bảo vệ hành động trang và username vẫn chỉ dành cho người đã đăng nhập

Changed

  • •boardPreloadUsers(array $rows) được thêm (board/_init.php) — tải hàng loạt danh sách user_id trong một truy vấn IN duy nhất, chia sẻ qua cache $GLOBALS['_boardUserCache']
  • •boardAuthorMention() được mở rộng — thêm thuộc tính data-user-username·data-user-avatar (liên kết URL story /story/{username} chính xác, hiển thị ảnh đại diện). Ưu tiên HIT cache prebload, dùng truy vấn đơn lazy khi miss
  • •board/list.php·board/read.php·skins/board/qna/_list-full.php — gọi boardPreloadUsers() trước khi render để ngăn truy vấn N+1

Fixed

  • •Mở rộng parser hiển thị (resources/views/system/changelog/index.php) — thêm render cho code fence (``), bảng (|...|), liên kết markdown (text), tiêu đề phụ #### và đường kẻ ngang (---`). Khắc phục việc các phiên bản trước (2.4.1·2.3.8·2.3.7 v.v.) dùng cú pháp này bị hiển thị dưới dạng markdown thô
  • •Fallback locale theo từng phiên bản — chuyển từ việc lấy toàn bộ danh sách bằng một ngôn ngữ sang theo từng phiên bản (locale hiện tại → en → ko). Giờ mọi phiên bản đều xuất hiện ở bất kỳ ngôn ngữ nào, và các phiên bản chưa dịch hiển thị huy hiệu ngôn ngữ dự phòng
  • •Căn chỉnh ranh giới khối (rzxlib/Core/Changelog/ChangelogParser.php) — ngăn tiêu đề ## [Unreleased] không có ngày bị hút vào phiên bản trước đó (vd 1.5.0) bằng cách tách khối tại mọi ## [
v2.6.3 2026-05-25 · 5 tháng trước
Thống kê tải xuống bản phân phối · Tách widget hero · Trình tạo kéo-thả

Added

  • •Migration 056 bảng dist_downloads (site_id·version·ip·user_agent·referrer·utm_*·is_bot·created_at)
  • •Endpoint tải xuống api/dist-download.php — thay vì liên kết trực tiếp tĩnh /download/*.zip, yêu cầu đi qua nó để ghi nhận thống kê theo phiên bản / theo ngày / nguồn (referrer·UTM) rồi chuyển hướng 302. UA bot được đếm riêng; danh sách trắng phiên bản (chống path-traversal)
  • •Trang thống kê quản trị resources/views/admin/dist-downloads.php (chỉ master, 13 ngôn ngữ) — thẻ tóm tắt (tổng/hôm nay/7n/30n), cột theo phiên bản, xu hướng theo ngày (30n), Top-10 nguồn, UTM. Biểu đồ SVG/CSS tự xây (không thư viện ngoài)
  • •Đổi liên kết tải của widget download-hero sang endpoint đếm
  • •Thêm menu quản trị "Thống kê tải xuống" (config/admin-menu.php, chỉ master)

Added

  • •hero-cta-text — vùng văn bản phía trên (gõ chữ). Giá trị mặc định khớp với nội dung hero-cta2 đang chạy (13 ngôn ngữ); cài đặt người dùng được ưu tiên
  • •hero-cta-button — nút tải xuống (tự phát hiện phiên bản mới nhất + đếm lượt tải, không cần cấu hình) cùng nút marketplace tùy chọn (một nút nếu để trống)
  • •Nhãn và giá trị mặc định của biểu mẫu cài đặt bằng 13 ngôn ngữ (hỗ trợ đối tượng getLabel của trình tạo)
  • •Thống nhất màu/nền nút tải xuống với hero-cta2 (#2563eb)

Added

  • •Kéo thẻ bảng chọn vào canvas để thêm widget (nhóm pull:'clone' của SortableJS + thay bằng khối thật trong onAdd của canvas). Hoạt động song song với thêm bằng nhấp và sắp xếp ↑↓/tay cầm hiện có
  • •Flyout vẫn mở khi kéo + làm nổi vùng thả trên canvas (wb-drop-active)

Changed

  • •Bỏ khoảng cách bọc trang giữa các widget (type-widget.php py-2 → 0)
  • •Ổn định dịch AI bình luận đồng bộ — nginx fastcgi_read_timeout 150s (vhost diễn đàn) · PHP-FPM request_terminate_timeout 150 · set_time_limit 150, OllamaProvider keep_alive 30 phút (mô hình thường trú, loại bỏ tải nguội)
  • •Thêm nút sao chép cho Webhook URL và Redirect URI ở tab Message API và Đăng nhập mạng xã hội (13 ngôn ngữ, có dự phòng cho ngữ cảnh không an toàn)
v2.6.2 2026-05-14 · 5 tháng trước
Tự động hóa thuế quyết toán, phân nhánh biểu mẫu và SSOT trang hệ thống

Added

  • •Migration 036 — thêm cột withholding_tax · consumption_tax · tax_basis vào partner_earnings / payouts
  • •Migration 037 — thêm cột fx_rate · fx_amount · fx_currency vào payouts (ghi nhận chuyển khoản đã quy đổi sang USD)
  • •Migration 038 — thêm cột vcs_developers.paypal_email
  • •Helper rzxlib/Core/Helpers/MarketTax::calculate() — mô hình khấu trừ chuẩn Nhật Bản

· Giá bán đã bao gồm thuế (税込); marketplace nộp thuế GTGT trực tiếp cho NTA

· freelance → khấu trừ thuế 10,21% / invoice_eligible → khấu trừ thuế đầu vào / no_invoice → không nộp thuế GTGT

· Không có phân loại hoặc chưa nhập dữ liệu → bắt buộc áp dụng freelance (thận trọng: trả thiếu có thể hoàn trả, trả thừa không thu hồi được)

  • •Script bổ sung ngược scripts/market-tax-backfill.php — tính lại earnings/payouts hiện có (bảo vệ status='paid', hỗ trợ --dry-run)
  • •Hiển thị quyết toán 5 phần: doanh thu → hoa hồng → khấu trừ thuế GTGT → khấu trừ thuế (freelance) → số tiền thực nhận
  • •Khóa mới trong rzx_mkt_settings: min_payout_amount · consumption_tax_rate · default_commission_rate (settings ưu tiên ở mọi nơi; loại bỏ fallback cứng)

Added

  • •Modal quyết toán tại /theadmin/market/partners/payouts — prompt() × 2 + alert() → modal đơn nhất

· JOIN với vcs_developers để tự động điền sẵn ngân hàng/chi nhánh/chủ tài khoản/số tài khoản/loại hình doanh nghiệp/số T (prefill; PII enc: tự động giải mã)

· Tính tự động 5 phần + chip cơ sở pháp lý Nhật Bản (freelance_withholding, v.v.) + trích dẫn điều khoản (§204, hệ thống hóa đơn)

· Thông báo toast ngay trong trang; đóng modal và tự động tải lại

  • •Tự động quy đổi sang USD cho tài khoản ngoài quốc gia hoạt động (Migration 037)

· Tỷ giá tự động Frankfurter API (cache lưu trữ TTL 24 giờ) + ghi đè thủ công bởi quản trị viên (TTS ngân hàng)

· Tự động chọn method=paypal

· Đối với người nước ngoài: ẩn thẻ tài khoản ngân hàng, hiển thị thẻ email PayPal (bank_country == site_country)

  • •Nhà phát triển tự chỉ định số tiền quyết toán (/mypage/developer/earnings)

· Toàn bộ số dư → nhập số tiền + nút toàn bộ + kiểm tra số tiền tối thiểu

· Cột 5 phần cho lịch sử bán hàng, hộp thông tin quyết toán (luật thuế áp dụng theo loại hình doanh nghiệp)

  • •Thông tin phụ quy đổi USD và tỷ giá trong lịch sử thanh toán (cả màn hình quản trị viên và nhà phát triển)
  • •Thay thế biểu đồ xu hướng doanh số bằng biểu đồ thanh SVG (khắc phục vấn đề hiển thị thanh div)

Added

  • •Chính sách khóa dựa trên tax_review_status (hồ sơ nhà phát triển)

· not_submitted / rejected → có thể chỉnh sửa

· pending / approved → khóa chỉnh sửa (ổ khóa + cảnh báo)

· rejected → có thể chỉnh sửa + gợi ý "khi lưu sẽ vào hàng đợi xét duyệt"

· Bảo vệ phía máy chủ: HTTP 423 Locked (chặn bypass giao diện)

  • •update.php cập nhật từng phần an toàn — UPDATE động chỉ các trường được gửi (trước đây: ghi đè toàn bộ có nguy cơ NULL với các trường không gửi)
  • •Liên kết đến trang xác minh chính thức (màn hình xác minh quản trị viên + hồ sơ nhà phát triển)

· 🇯🇵 Trang công bố số pháp nhân của NTA (https://www.houjin-bangou.nta.go.jp/)

· 🇯🇵 Trang công bố nhà phát hành hóa đơn đủ điều kiện của NTA (https://www.invoice-kohyo.nta.go.jp/regno-search/)

· 🇰🇷 Tra cứu trạng thái đăng ký doanh nghiệp trên Hometax Hàn Quốc

· Nút sao chép một chạm bên cạnh số doanh nghiệp/số T

Added

  • •Đăng ký mới (/mypage/developer) — chuyển lựa chọn quốc tịch lên đầu biểu mẫu, có hướng dẫn so sánh với quốc gia hoạt động

· country == site_country → 🏠 biểu mẫu trong nước (loại hình doanh nghiệp / tài khoản ngân hàng)

· country != site_country → 🌐 biểu mẫu nước ngoài (tự động freelance + email PayPal bắt buộc)

· Getter isDomestic Alpine.js, hằng số toàn cục OPERATING_COUNTRY

  • •Chỉnh sửa hồ sơ (/mypage/developer/profile) — cùng cấu trúc (quy tắc [feedback_admin_user_parity])

· Người nước ngoài: ẩn phần doanh nghiệp; thông tin quyết toán = chỉ email PayPal

· Quốc tịch bị khóa (liên hệ quản trị viên để thay đổi), hiển thị chip chế độ ở trên

  • •Xác thực phía máy chủ của API đăng ký — email PayPal bắt buộc với người nước ngoài, freelance bắt buộc áp dụng, giá trị doanh nghiệp/tài khoản bị bỏ qua

Added

  • •Tự động thay thế token trong page.php — áp dụng chung cho tất cả trang hệ thống

· {{COMPANY_NAME}} {{COMPANY_ADDRESS}} {{COMPANY_PHONE}} {{COMPANY_EMAIL}} {{COMPANY_REG_NUMBER}} {{COMPANY_REPRESENTATIVE}}

· {{SITE_NAME}} {{SITE_URL}} {{DOMAIN}}

· Ánh xạ tự động từ settings business_ hoặc site_ của quản trị

· page_title / page_subtitle tùy chỉnh cũng đi qua thay thế token

  • •Thứ tự ưu tiên {{DOMAIN}} — official_domain (tên miền chính thức cho điều khoản và chính sách) → host của site_url

· Ngay cả trên máy chủ phát triển vos.21ces.com, nội dung điều khoản vẫn hiển thị voscms.com

Added

  • •Thay thế toàn bộ terms / privacy trong rzx_page_contents (mỗi loại 13 dòng) — Điều khoản nền tảng đặt lịch RezlyX → Điều khoản phần mềm miễn phí VosCMS
  • •Điều khoản sử dụng 18 điều: mục đích · định nghĩa · công bố và sửa đổi · quy tắc bổ sung · ký kết hợp đồng · quyền riêng tư · thông báo · nghĩa vụ công ty · nghĩa vụ người dùng · cung cấp dịch vụ · thay đổi · hạn chế sử dụng · giấy phép (sử dụng miễn phí) · quyền sở hữu và lưu trữ dữ liệu · bản quyền bài đăng · tuyên bố miễn trừ trách nhiệm (AS-IS) · bồi thường thiệt hại · giải quyết tranh chấp
  • •Chính sách quyền riêng tư 10 điều: mục đích xử lý · danh mục · thời hạn lưu trữ · chuyển giao và ủy thác cho bên thứ ba · quyền của chủ thể dữ liệu · biện pháp bảo mật · cookie · người chịu trách nhiệm bảo vệ · khắc phục vi phạm (PPC) · thay đổi
  • •Luật Nhật Bản + thẩm quyền độc quyền Tòa án Quận Fukuoka, trích dẫn APPI §33·§34·§35
  • •Thông tin công ty dùng token → chỉnh sửa một lần trong quản trị sẽ tự động đồng bộ cả điều khoản và chính sách
  • •Phiên bản tiếng Nhật là văn bản chính thức; dịch chính thức bằng ngôn ngữ bản địa cho 13 ngôn ngữ
  • •Thẻ thông tin công ty — chỉ 3 mục: tên pháp lý, địa chỉ và điện thoại (loại bỏ tên đại diện để tránh sửa đổi điều khoản khi thay đổi đăng ký)
  • •Script lưu trữ: scripts/voscms-terms-update.php · scripts/voscms-privacy-update.php

Fixed

  • •menus-api.php tại /theadmin/site/menus đi sau vos 99 dòng, khiến bỏ qua xác thực và dịch khi lưu/chỉnh sửa menu
  • •Đồng bộ menus-api.php từ vos → market:

· mn_link_target_exists() — menu lối tắt (liên kết) chỉ được lưu sau khi xác nhận trang đích (trang hệ thống · rzx_page_contents) tồn tại

· Bảo vệ tái sử dụng ID menu — tự động dọn dẹp rzx_translations.menu_item.{id}.* cũ cho ID mới

· Phương thức INSERT cho bản dịch: INSERT IGNORE → INSERT … ON DUPLICATE KEY UPDATE (cho phép ghi đè)

· Khi thay đổi title·url: xóa toàn bộ bản dịch cũ + tự động đăng ký lại bản dịch khi khớp với trang hệ thống (config/system-pages.php)

  • •Thêm 4 tệp admin/site/menus*.php vào INCLUDES của sync-to-market.sh

Fixed

  • •Bảng rzx_contact_messages bị thiếu → thêm migration 041_create_contact_messages.sql (IF NOT EXISTS, không ảnh hưởng đến vos hiện có)
  • •Bố cục kép trong contact-messages.php — _head.php đã xuất sidebar+topbar nhưng view lại include trực tiếp thêm một lần nữa, dẫn đến <body> trùng và main lồng nhau. Sắp xếp lại theo mẫu vos (đầu = _head 1 lần, chân = _foot 1 lần)

Added

  • •Migration 040 040_create_developer_platform.sql — tạo đồng thời 7 bảng: vcs_developers + vcs_developer_earnings/payouts/activity/notes + vcs_review_queue + rzx_mp_items (IF NOT EXISTS, schema cuối sau khi áp dụng ALTER 030~038)

· vcs_developers trên vos.21ces.com chỉ tồn tại trong dump mà không có migration CREATE TABLE — khắc phục lỗi ALTER 030 trên các site được tạo sau

  • •Đồng bộ mypage/profile-sidebar.php — truy vấn rzx_mkt_partners (cũ) → truy vấn vcs_developers (mới) (tích hợp hoạt động nhà phát triển trong trang cá nhân)
  • •Vá route index.php market (thủ công, tránh sync toàn bộ):

· /developer/ → /mypage/developer/ chuyển hướng 301 (ánh xạ login/dashboard/my-items/submit/earnings/profile/logout)

· Route mypage/developer/{register|items|items/new|earnings|profile} + mypage/developer/items/{N} + mypage/developer/items/{N}/edit

  • •Thêm migration 040 + profile-sidebar.php vào INCLUDES của sync-to-market.sh
  • •Sao lưu tự động DB market (storage/backups/market-YYYYMMDD-HHMMSS/market_vos.sql) trước khi áp dụng migration 040

Added

  • •Điều khoản market.21ces.com theo mô hình marketplace vận hành bởi bên thứ ba, riêng biệt với điều khoản phần mềm miễn phí VosCMS
  • •Điều khoản 18 điều (phản ánh quy tắc vận hành marketplace):

· Điều 8: hợp đồng mua bán được xác lập giữa người mua và nhà phát triển; công ty là trung gian thanh toán và giao hàng

· Điều 9: bốn ngoại lệ hoàn tiền cho sản phẩm kỹ thuật số (trước khi tải xuống · mô tả không khớp 7 ngày · xác nhận phần mềm độc hại · lỗi hệ thống) — đáp ứng yêu cầu công bố Điều 15-2 Luật Giao dịch Thương mại Đặc thù Nhật Bản

· Điều 10: không ghi rõ tỷ lệ hoa hồng (tham chiếu "mức được công bố riêng"; có thể điều chỉnh mức mà không cần sửa điều khoản)

· Điều 10: khấu trừ 10,21% theo Điều 204 Luật Thuế Thu nhập Nhật Bản; với người có số T, marketplace nộp thuế GTGT trực tiếp cho NTA; tài khoản ngoài quốc gia hoạt động → chuyển khoản PayPal bằng USD

· Điều 14: điều khoản riêng của nhà phát triển được ưu tiên — trừ các vấn đề vận hành nền tảng (thanh toán, quyết toán, quy trình hoàn tiền)

· Điều 17: giới hạn bồi thường: tổng hoa hồng/quyết toán 6 tháng trước

· Điều 18: luật Nhật Bản + thẩm quyền độc quyền Tòa án Quận Fukuoka

  • •Chính sách quyền riêng tư 12 điều (từ góc độ marketplace ba bên):

· Danh mục dữ liệu — chung / người mua / nhà phát triển (chung) / cư trú tại Nhật / cư trú ở nước ngoài / giao hàng: 6 danh mục

· Thời hạn lưu trữ — thành viên 1 năm · giao dịch 7 năm · quyết toán/khấu trừ thuế 7 năm · xác minh danh tính 5 năm · log 6 tháng · yêu cầu 3 năm

· Đơn vị xử lý dữ liệu — Stripe · KOMOJU · PayPal · Frankfurter · SendGrid · NTA nêu rõ tên

· Chuyển giao quốc tế — Mỹ (PayPal/Stripe/SendGrid) · EU (tỷ giá) · các nước khác (cổng thanh toán/ngân hàng địa phương) nêu rõ tên

  • •Script: scripts/market-terms-update.php · scripts/market-privacy-update.php (UPSERT — UPDATE trước; INSERT nếu không có dòng)
  • •DB market đã cập nhật (terms/privacy, mỗi loại 13 dòng trong rzx_page_contents), tiêu đề và phụ đề đa ngôn ngữ page-i18n cũng được áp dụng

Added

  • •Khắc phục ánh xạ thiếu của cài đặt skin (page_title · page_subtitle) — giá trị nhập ở màn hình cài đặt không hiển thị trên trang
  • •Tạo partial _page-title-bg.php còn thiếu (khắc phục cảnh báo include trong nginx error log)
  • •Thêm tùy chọn color vào title_bg_type + trường title_bg_color — tự động fallback về màu khi ảnh/video trống
  • •Loại bỏ fallback hộp trắng khi content_bg=transparent (khắc phục nội dung max-w-5xl trông hẹp trong thẻ)
  • •Biến CSS --page-content-width tự động xuất — các component được include từ bên ngoài như thanh hành động "Về trang này" (vos-community) căn chỉnh cùng chiều rộng với content_width của trang

Fixed

  • •PDOException trên trang quyết toán — xóa tham chiếu đến cột p.currency không tồn tại trong rzx_mkt_partners
  • •Biểu đồ xu hướng doanh số không hiển thị — thanh div với chiều cao % hầu như là 0px tùy môi trường → thay bằng biểu đồ dựa trên SVG viewBox (đảm bảo hiển thị tối thiểu 4px)
v2.6.1 2026-05-13 · 5 tháng trước
Mở Rộng Cổng Thông Tin Nhà Phát Triển · i18n Trang Quản Trị Marketplace · Tương Tác Trang Công Khai

Added

  • •Màn hình chi tiết mục trong trang nhà phát triển (/mypage/developer/items/{id}) — thống kê, lịch sử phát hành, xu hướng tải xuống
  • •Màn hình chỉnh sửa mục nhà phát triển (/mypage/developer/items/{id}/edit) — giao diện 3 tab giống items-new, điền sẵn các giá trị hiện có, tải lên ZIP mới theo luồng riêng
  • •API mới: /api/developer/item-update — cập nhật name(JSON), short/desc(JSON), tags(JSON), price, license, repo/demo URL, dependencies, minimum version, icon, screenshots
  • •API mới: /api/developer/request-payout — yêu cầu thanh toán
  • •API mới: /api/developer/update-bank — cập nhật tài khoản thanh toán của chính mình
  • •API mới: /api/developer/issue-reply — đăng trả lời Q&A (kênh phản hồi của chính nhà phát triển)
  • •Màn hình chi tiết nhà phát triển trong admin (/theadmin/developers/show) — thẻ doanh nghiệp/tài khoản/tài liệu + chế độ xem xét tài liệu (phê duyệt/từ chối)
  • •Xác minh email khi đăng ký và đăng nhập (/verify-email) được cải thiện + trường company được lưu trong Auth::register
  • •Thêm khóa dịch chính thức 13 ngôn ngữ (show_edit_btn, items_edit_*, items_back_detail, api_updated, v.v.)

Added

  • •Form gửi đánh giá, vấn đề và Q&A được hiển thị trực tiếp trong widget (không cần chuyển trang)
  • •Chỉ người mua mới có thể gửi — người chưa mua thấy form nhưng nhận thông báo tại thời điểm gửi
  • •Trả lời Q&A hỗ trợ phân chuỗi (trả lời câu trả lời) — DB migration 035 (parent_reply_id)
  • •API mới: /plugins/vos-market/views/api/item/post-issue.php, post-reply.php, post-review.php
  • •Core rzxlib/Core/Helpers/Notifications.php — helper thông báo (kết hợp với DB migration 034)

Added

  • •Hỗ trợ đầy đủ 13 ngôn ngữ áp dụng cho tất cả màn hình: /theadmin/market/licenses, sync, orders, settings, submissions, partners/payouts, items
  • •Màn hình cài đặt marketplace — nhãn "Đối tác" thống nhất thành "Nhà phát triển" (chỉ văn bản hiển thị; tên biến giữ nguyên để tương thích)
  • •Nhập tên mục marketplace sử dụng modal nhập liệu đa ngôn ngữ dùng chung — name_json được chỉnh sửa đồng thời trong 13 ngôn ngữ
  • •plugins/vos-market/lang/* — nhóm ngôn ngữ mới ở cấp plugin
  • •resources/lang/*/marketplace.php — 13 ngôn ngữ đều được dịch sang ngôn ngữ bản địa (tuân thủ quy tắc dịch đầy đủ i18n)

Added

  • •033_developer_notes_activity.sql — ghi chú và nhật ký hoạt động theo từng nhà phát triển
  • •034_notifications.sql — bảng rzx_notifications (thông báo người dùng)
  • •035_issue_reply_thread.sql — cột rzx_mkt_issue_replies.parent_reply_id được thêm (trả lời theo chuỗi)

Fixed

  • •/Market?item={slug} thiếu slug — được sửa trong items-show bằng truy vấn một cột riêng biệt
  • •Tên cột icon_url trong API cập nhật mục được sửa thành tên cột thực icon
  • •Trang cài đặt marketplace hiển thị trống — áp dụng migration 005 bị thiếu cho rzx_mkt_settings
v2.6.0 2026-05-06 · 6 tháng trước
Tên người dùng thành viên · Plugin vos-story · Thiết kế lại Trang của tôi · Phản chiếu hình ảnh ngoài · Tích hợp Cài đặt Hosting

Added

  • •VARCHAR(12) users.username + UsernameValidator (tối thiểu 6 ký tự, hạn chế ký tự đặc biệt)
  • •Modal cổng khi truy cập lần đầu sau đăng nhập (AJAX /api/username-set)
  • •Bản dịch chính thức cho 13 ngôn ngữ (xóa fallback tiếng Anh)

Added

  • •/profile/{uuid} → /story/{username} chuyển hướng 301
  • •Nhãn menu ngữ cảnh đổi từ "Xem hồ sơ" thành "Xem câu chuyện"

Added

  • •Plugin vos-story tách từ core — chuyên dụng cho /story/{username}
  • •Header kiểu Facebook + 5 tab cố định (Tất cả / Thông tin / Ảnh / Người theo dõi / Đang theo dõi)
  • •CRUD bài viết + SNS feed (vos_story_posts, body_format = text/html)
  • •Nút chuyển TEXT/EDIT + tích hợp Summernote
  • •Đính kèm ảnh (nhiều ảnh) + lưới tab Ảnh
  • •Hệ thống thích + bình luận
  • •Hệ thống skin Story (skins/story/default) + token theo người dùng (/mypage/story)
  • •Trang chính sách admin (/admin/vos-story/policy)
  • •Thanh hành động trang: i18n + vị trí (cuối nội dung chính) + token chiều rộng nội dung
  • •Lưới 2:1 (chỉ vùng nội dung) — bên phải: quảng cáo + bạn bè (tab Người theo dõi/Đang theo dõi)
  • •Nút hành động tiêu đề — chỉ biểu tượng ([Cài đặt Story của tôi] / [Chỉnh sửa hồ sơ] / [Theo dõi])

Added

  • •D-1: Thanh bên 4 menu (Bảng điều khiển / Câu chuyện / Tài khoản / Tin nhắn)
  • •D-2-A: Bảng điều khiển mới — 8 thẻ trạng thái + điều hướng 8 tab + tab thông tin tài khoản
  • •D-2-B: Tab Lưu trữ / Hộp thư đến / Bạn bè (mỗi tab có liên kết "Xem tất cả")
  • •D-2-C: Tab Đã lưu / Bài viết của tôi / Bình luận của tôi (bảng tin + Story + trang hợp nhất)
  • •D-2-D: Quản lý đăng nhập tự động (remember tokens)

Added

  • •Helper dùng chung rzx_mirror_external_images() — cURL + bảo vệ SSRF + thay đổi kích thước GD
  • •E-1: Chụp ảnh chụp màn hình lưu trữ + hấp thụ hình ảnh ngoài
  • •E-2: Hấp thụ khi tạo bài đăng Story (cột source của story_attachments)
  • •E-3: Hấp thụ khi tạo bài đăng bảng tin
  • •E-4: Hấp thụ khi tạo nội dung trang
  • •Đánh dấu ảnh: data-source-original, data-source-mirrored

Added

  • •Thanh bên quản lý hosting — mục cuối [Cài đặt] dẫn đến 4 tab của trang yêu cầu dịch vụ (general/domain/hosting/addons)
  • •Chính sách hoàn tiền → Cài đặt hệ thống → Chung → thẻ riêng biệt (tách khỏi cài đặt thuế)
  • •Lưu trữ khóa đơn rzx_settings.refund_policy
  • •Khóa settings.refund.* cho 13 ngôn ngữ

Added

  • •Migration 009: cột page_contents.created_by / updated_by
  • •Tự động ghi lại trên tất cả màn hình chỉnh sửa trang (admin/customer/system)

Added

  • •Đếm bài viết — nhận biết cấu trúc tách riêng rzx_translations cho bài đăng bảng tin (board_post.{id}.title)

Added

  • •Cài đặt admin cho hạn ngạch lưu trữ theo hosting / ngưỡng cảnh báo / chính sách (block/notify/none)
  • •Biểu đồ vòng sử dụng trong Trang của tôi
  • •Màn hình nền scripts/db-quota-monitor.php

Added

  • •Nút cài đặt lại VosCMS — tab hosting của admin
  • •Hành động thay đổi [Trạng thái] hosting + nhật ký
  • •Xóa biểu mẫu chỉnh sửa "Cài đặt thông tin kết nối máy chủ" (ngăn lộ thông tin không cần thiết)

Fixed

  • •Lỗi mạng scrap add_scrap — xung đột require file API vos-story
  • •Thẻ lưu trữ — viền + biểu tượng xóa/chỉnh sửa (thùng rác)
  • •Sai lệch giữa số lượng bài viết và danh sách (thiếu bộ lọc trạng thái)
  • •Xóa khớp nick_name (ngăn nhận dạng nhầm dữ liệu seed có user_id NULL)
  • •Vị trí menu Story trong Trang của tôi — top → main (tự động nhận dạng plugin)
  • •Biểu tượng menu Story ở định dạng core (thẻ <path> đầy đủ)
  • •Thiếu cột key trong settings SELECT của tab dịch vụ bổ sung (hai phần bị ẩn)
  • •Hành động hosting_status 500 — vị trí định nghĩa hàm helper
  • •Thanh hành động trang — token chiều rộng nội dung được áp dụng
  • •Lỗi bài viết cũ biến mất khi đăng bài mới (cập nhật feed ngay lập tức)
v2.5.0 2026-05-01 · 6 tháng trước
Modal Thêm Tên miền + Sổ Kế toán + Thanh toán Add-on + Hạ tầng Hỗ trợ

Added

  • •Chi tiết hosting → Tab domain → Nút + Thêm Domain → modal
  • •Tùy chọn: subdomain miễn phí / đăng ký mới / kết nối domain đã có
  • •Tìm kiếm WHOIS (/api/domain-check.php tái sử dụng) + hiển thị giá theo TLD
  • •Thanh toán: thẻ đã lưu (tái sử dụng khách hàng PAY.JP của hosting) hoặc thẻ mới (PAY.JP Elements)
  • •Tự động tách thuế tiêu thụ 10% (tạm tính / thuế / tổng cộng)
  • •Khi thanh toán hoàn tất, thêm vào hosting sub metadata.added_domains[] (không tạo sub riêng)
  • •Lưới an toàn hoàn tiền tự động — khi xử lý DB thất bại, khoản tính tiền PAY.JP tự động được hoàn

Added

  • •Ngày bắt đầu~hết hạn + Nút kiểm tra (DNS A/CNAME → khớp vùng của chúng tôi hoặc dải IP Cloudflare)
  • •Bật/tắt tự động gia hạn + Nút yêu cầu gia hạn (theo từng domain)
  • •registrar_pending / manual_attach_pending: nút kiểm tra → huy hiệu "Đang xử lý"
  • •Huy hiệu tím "Domain đã thêm"

Added

  • •Thanh bên quản lý hosting: mục thứ 2 được thêm mới
  • •Danh sách thống nhất: sub type='domain' + hosting sub.added_domains[] tất cả hiển thị theo thứ tự thời gian
  • •Thẻ thống kê (tổng/đang chờ/hoàn thành) + bộ lọc (trạng thái/tùy chọn/tìm kiếm)
  • •Hành động: [Đánh dấu đã đăng ký] / [Xử lý hủy] (khi hủy: hoàn tiền PAY.JP + INSERT dòng hoàn tiền)
  • •Tự động giải mã tên người dùng

Added

  • •Thanh bên quản lý hosting: mục thứ 3 được thêm mới
  • •Sổ giao dịch dựa trên rzx_payments — thẻ thống kê doanh thu/hoàn tiền/doanh thu ròng/thuế
  • •Tự động tính số tiền gốc cho khai thuế tiêu thụ Nhật Bản (giá đã có thuế → gốc = total × 100/110, thuế = total × 10/110)
  • •Bảng xu hướng 12 tháng gần nhất + bảng sổ giao dịch + bộ lọc/phân trang

Added

  • •Tab add-on trang cá nhân: mục "Có thể đăng ký" (email doanh nghiệp tự động loại trừ)
  • •Hành động theo giá:
  • •Miễn phí (hỗ trợ cài đặt): thông báo admin + order_logs
  • •Báo giá (tùy chỉnh): "Yêu cầu báo giá"
  • •Giá cố định định kỳ (hỗ trợ kỹ thuật 1 năm): modal thanh toán thẻ (_addon-pay-modal.php)
  • •Khi thanh toán hoàn tất, addon sub tự động được tạo + bút toán payments
  • •Nhãn sub đã hoạt động khớp: nút đăng ký tự động vô hiệu
  • •Dòng install_info bên phải: nút [Vào Admin / Vào Website]

Added

  • •Sơ đồ DB: UNIQUE uk_payment_order bị xóa → UNIQUE uk_payment_key (charge_id) thay thế
  • •Cho phép nhiều dòng thanh toán trên một đơn hàng (hosting + domain + add-on tích lũy)
  • •Khi hoàn tiền: dòng đã thanh toán không thay đổi, INSERT dòng hoàn tiền riêng (status='refund', tính toàn vẹn kế toán)
  • •Nghĩa vụ lưu giữ 7 năm của Nhật Bản + tiêu chuẩn phản hồi tranh chấp thương nhân PAY.JP được đáp ứng

Added

  • •composer require minishlink/web-push
  • •Trình trợ giúp gửi push dựa trên VAPID cho admin/supervisor
  • •Tự động dọn dẹp endpoint hết hạn + tự động ghi vào rzx_push_messages
  • •Điểm gọi: pay_domain (thanh toán domain hoàn tất), service-order (yêu cầu đăng ký domain), request_addon

Added

  • •Tự động khớp subdomain vùng của chúng tôi (nhận dạng CNAME wildcard)
  • •Khớp 15 dải CIDR IPv4 Cloudflare (khi có phản hồi proxy)
  • •Phản hồi "already_refunded" được xử lý là thành công (khi PAY.JP đã hoàn tiền)

Added

  • •Truy vấn con tổng hợp rzx_payments (paid − refunded)
  • •Hiển thị tích lũy thanh toán cơ bản hosting + thêm domain + thanh toán add-on

Added

  • •admin_cancel_addon — sub status='cancelled' + hoàn tiền PG + INSERT dòng hoàn tiền
  • •Định tuyến PG: dựa trên cột gateway của dòng thanh toán (an toàn ngay cả sau khi thay PG)

Removed

  • •Theo nghĩa vụ lưu giữ 7 năm của Nhật Bản + chính sách phản hồi tranh chấp PAY.JP, tất cả nút "xóa" trong giao diện admin đã bị loại bỏ
  • •Biểu tượng thùng rác + adminDeleteAddon JS + admin_delete_addon API + 4 nhãn trong 13 ngôn ngữ tất cả bị loại bỏ
  • •Chỉ dùng "Hủy" — dòng dữ liệu không bao giờ bị xóa (DELETE)

Fixed

  • •Xung đột tiền tố dấu hai chấm trong placeholder Translator — [':count' => N] → ['count' => N] sửa hàng loạt
  • •metadata[refund_reason] của PayjpGateway::refund() bị PAY.JP từ chối → đổi thành refund_reason
  • •Kiểm tra quyền admin trong service-manage.php — role === 'admin' → role IN ('admin','supervisor') sửa trên 5 hành động
  • •Tab domain đơn hàng dịch vụ: sau hoàn tiền, thẻ kế toán hiển thị âm → logic SQL được sửa (tổng riêng status='paid' / 'refund')

Added

  • •ssh.21ces.com Cloudflare Tunnel đã đăng ký (Public Hostname: SSH → localhost:22)
  • •PC bên ngoài: cloudflared access ssh --hostname ssh.21ces.com hoặc ProxyCommand trong ~/.ssh/config
  • •Phía máy chủ: PermitRootLogin no, khóa thevos đã đăng ký
v2.4.3 2026-04-29 · 6 tháng trước
Cài đặt tự động VosCMS + Sao lưu trang quản lý hosting / phpMyAdmin

Added

HostingProvisioner.php installVoscms() giờ gọi install-core.php theo trình tự step 3 → step 4 sau khi triển khai zip (trước đây chỉ step 2):

  • •Mới runInstallCoreSteps() — bỏ qua phiên bằng fallback POST _db + xác minh marker .installed
  • •Mới callInstallCore() — HTTP loopback (cổng 80, tận dụng SSL edge Cloudflare; xử lý trường hợp thiếu chứng chỉ origin khi rate limit)
  • •Mới appendHostingEnv() — tái nạp các biến HOSTING_* sau khi install-core.php ghi đè .env
  • •Tự động xóa welcome.html sau khi cài đặt hoàn tất (để VosCMS index.php được ưu tiên)
  • •Luồng thanh toán service-order.php:567-576 — khi cài đặt thành công, tự động ghi install_completed_at và install_admin_url vào metadata addon (kích hoạt hiển thị tab trang quản lý)

Added

admin/service-orders/detail.php:175-260 + partials/addon.php:

  • •Addon "Hỗ trợ cài đặt" trong tab dịch vụ bổ sung có hai nút:
  • •Cài VosCMS (tím) — hiển thị khi có install_info và chưa có install_completed_at
  • •Trang quản trị (xanh lá) — mở URL admin trong tab mới sau khi cài đặt
  • •API action admin_run_voscms_install — gọi trực tiếp HostingProvisioner.installVoscms(), fallback thông tin đăng nhập DB từ metadata.server.db hoặc .env của khách hàng
  • •Khi thành công: ghi metadata addon + bản ghi voscms_installed trong order_log

Added

customer/mypage/service-partials/hosting.php:

  • •🟢 Nút Sao lưu trang web — service-manage.php?action=request_backup (mới)
  • •mysqldump → dump DB + đóng gói zip (public_html, .env, sql)
  • •URL tải xuống có chữ ký (HMAC, hết hạn 10 phút) — api/backup-download.php mới
  • •Tự động xóa bản sao lưu cũ hơn 7 ngày
  • •🟣 Nút Mở phpMyAdmin — https://pma.voscms.com/?lang=<user_locale> trong tab mới
  • •vhost nginx: pma.voscms.com.conf mới (tự động định tuyến qua wildcard Cloudflare Tunnel *.voscms.com)
  • •Đăng nhập bằng thông tin đăng nhập DB của chính người dùng
  • •Hiển thị thông tin kết nối DB (host / tên DB / user / mật khẩu có toggle)
  • •i18n 13 ngôn ngữ: btn_site_backup, btn_open_phpmyadmin, confirm_site_backup, backup_in_progress, backup_ready, f_password, password_notice, f_protocol

Added

customer/mypage/service-partials/_setup-monitor.php:

  • •Tách biệt các bước: thiết lập hosting → cài đặt tự động VosCMS
  • •Đơn hàng system_imported (hosting được đăng ký bởi quản trị viên, ví dụ vos.21ces.com) được kích hoạt ngay lập tức — hộp giám sát không hiển thị
  • •i18n mới 13 ngôn ngữ: setup_step_voscms_install

Changed

Bổ sung vào rsync exclude:

  • •5 plugin nội bộ (không được đưa vào các trang khách hosting):
  • •vos-developer, vos-hosting, vos-license-server, vos-market, vos-salon
  • •7 file SQL migration reservation (khách hosting không cài hệ thống đặt chỗ):
  • •001_create_reservation_tables.sql, 011_seed_service_translations.sql, 012_seed_service_translations_p2.sql, 013_add_source_to_reservations.sql, 014_add_payment_status_to_reservations.sql, 015_create_reservation_core.sql (mới), 016_alter_reservation_services.sql, 024_reservations_bundle_columns.sql

Bổ sung vào danh sách xóa file dev:

  • •Thư mục admin/ (phần dư của offline.html) — thư mục rỗng gây 403 do nginx directory indexing, chỉ root /offline.html được sw.js tham chiếu
  • •Mã hóa cơ bản → obfuscate.php (ionCube EVAL cũ gây treo khi chạy; ionCube chỉ khi USE_IONCUBE=1)

Changed

Tách cấu trúc mà 001_create_base_tables.sql trước đây tạo cả bảng base lẫn reservation trong một file:

  • •Sửa đổi: 001_create_base_tables.sql — chỉ 5 bảng cốt lõi (rzx_admins, rzx_users, rzx_member_grades, rzx_settings, rzx_migrations) + seed cốt lõi (member_grades mặc định, settings mặc định)
  • •Mới: 015_create_reservation_core.sql — 9 bảng đặt chỗ (rzx_categories, rzx_services, rzx_service_options, rzx_reservations, rzx_payments, rzx_point_transactions, rzx_business_hours, rzx_holidays, rzx_staff_positions, rzx_staff) + seed đặt chỗ (business_hours, point_*)

Khi build bản phân phối hosting, 015 bị loại trừ → rzx_reservations không được tạo → $hasReservations = false tại admin/dashboard.php:25-27 → lịch không tự động hiển thị.

Các trang dùng hệ thống đặt chỗ (voscms.com, RezlyX, v.v.) áp dụng cả hai file SQL → không có thay đổi.

Changed

config/templates/nginx-vhost.conf.tpl + HostingProvisioner addHttpsToVhost():

  • •Cũ: cổng 80 (chuyển hướng HTTPS) + cổng 443 (nội dung thực) → vòng lặp redirect vô hạn với Cloudflare Tunnel + redirect 80→443
  • •Mới: một khối server thống nhất 80/443, phục vụ cùng nội dung, không có redirect
  • •fastcgi_read_timeout 60s → 300s (ngăn nginx timeout khi INSERT lớn)

Changed

  • •provision-hosting.php (công cụ CLI backfill): tự động cập nhật metadata đăng ký hosting (hosting_provisioned, server.{ftp,db,env}) — trước đây chỉ chạy _autoProvisionHosting của service-order.php
  • •Tự động xóa 5 plugin nội bộ + thư mục admin/

Added

Mới scripts/install-cli.php:

  • •Backfill gọi tự động install-core.php sau khi provisioning hosting
  • •Thông tin đăng nhập DB: ưu tiên metadata subscription, nếu không có thì fallback sang .env docroot của khách hàng
  • •Sử dụng: sudo -u www-data php scripts/install-cli.php --order=<ORDER>
  • •Khi thành công: tự động ghi install_completed_at vào metadata addon + action voscms_installed trong order_logs

Fixed

  • •Thiếu lời gọi _autoProvisionHosting() trong nhánh thanh toán thẻ — đã thêm
  • •install_info.admin_pw trong metadata thanh toán bị hiển thị dạng văn bản thuần — thống nhất mẫu toggle (👁) ở cả trang quản lý và trang quản trị

Migration Notes

  • •Khách hosting bên ngoài: không cần thao tác thêm. Build voscms-2.4.3.zip sử dụng zip sạch cho luồng cài đặt tự động.
  • •Trang chính (voscms.com): không có thay đổi (cả hai file SQL đều được áp dụng).
  • •Khách hosting hiện tại (dwhahn, v.v.): khuyến nghị deprovision + reprovision để cài đặt lại sạch (áp dụng zip mới sau khi tách).
  • •Dọn dẹp thủ công: /etc/nginx/sites-available/pma.voscms.com.conf được thêm mới — deploy trực tiếp lên hệ thống chính (ngoài rsync).
v2.4.2 2026-04-29 · 6 tháng trước
Hook thanh toán tự động hóa hosting + i18n nhật ký hoạt động

Added

Được gọi ngay sau khi thanh toán hoàn tất trong service-order.php:

  • •Hàm mới _autoProvisionHosting($pdo, $prefix, $orderId, $orderNumber) — chạy ngoài transaction thanh toán (tính toàn vẹn DB được cô lập; bản thân đơn hàng không bị ảnh hưởng nếu thất bại)
  • •Chỉ domain_option = 'free' được thiết lập ngay lập tức (tên miền phụ Cloudflare — đăng ký DNS tự động đã hoàn tất)
  • •new (chờ thay đổi NS sau khi mua domain) / existing (chờ thay đổi NS của domain đang có) ở trạng thái deferred — admin kích hoạt riêng tại thời điểm kích hoạt domain
  • •Nếu addon 'install' có install_info, các file voscms được deploy + .env được tạo tự động (tự động hóa luồng phiên từng bước của install-core.php (bước 2–5) đòi hỏi thiết kế lại toàn bộ pipeline cài đặt voscms — hoãn sang Giai đoạn 5; sau thanh toán, người dùng truy cập https://<domain>/install.php → thực hiện wizard với thông tin DB đã được nạp sẵn vào .env)
  • •Thông tin ftp/db/env được tự động lưu vào metadata.server của gói đăng ký hosting → tự động hiển thị trong tab hosting của Trang của tôi (không cần thay đổi UI)
  • •Hành động order_logs: hosting_provisioned / hosting_provision_skipped / hosting_provision_deferred / hosting_provision_failed

Thứ tự gọi: commit thanh toán → _autoProvisionHosting() → _autoProvisionMailDomain()

Added

$actionLabels trên trang chi tiết đơn hàng dịch vụ admin (detail.php:498-528) được mở rộng từ 8 lên 31 mục. Sửa lỗi mã hành động thô (ví dụ mail_account_added) hiển thị trong nhật ký hoạt động.

Ánh xạ hành động mới được thêm:

  • •Mail: mail_account_added/deleted, mail_address_changed, mail_provisioned/_skipped/_failed, mail_domain_migrated/activated, bizmail_upgrade_request
  • •Hosting: hosting_provisioned, hosting_provision_skipped/deferred/failed, hosting_deprovisioned
  • •Tiện ích bổ sung: admin_add_storage_addon, admin_delete_addon, storage_addon_paid/requested
  • •Hệ thống: customer_notified, setup_email_sent, server_info_updated, bulk_extended, manual_capacity_period_fix

Ngữ nghĩa màu sắc theo hành động: green (hoàn tất/tích cực), amber (đang chờ/cảnh báo), red (thất bại/đã xóa), blue (thông tin/thông báo), violet (admin/đặc biệt), zinc (trung lập).

23 khóa i18n — services.admin_orders.act_* — được thêm cho ko/ja/en (trang vận hành). 10 ngôn ngữ còn lại dùng tiếng Anh làm fallback.

Changed

Trong quá trình cấp phát hosting tự động, quá trình cài đặt VosCMS tự động chỉ thực hiện deploy file + tạo .env tự động. Tự động hóa luồng phiên từng bước của install-core.php (bước 2–5) đòi hỏi thiết kế lại toàn bộ pipeline cài đặt voscms — hoãn sang Giai đoạn 5. Sau thanh toán, người dùng truy cập https://<domain>/install.php → thực hiện wizard (thông tin DB đã được nạp sẵn vào .env).

Giá trị trả về của installVoscms() được thay đổi — giờ trả về install_url + thông báo note.

v2.4.1 2026-04-29 · 6 tháng trước
Tự động cấp phát hạ tầng hosting ảo hóa (Giai đoạn 1–3)

Added

HostingProvisioner.php — Lớp chính tự động thiết lập khi đặt hàng hosting. Giao dịch 9 bước (hoàn tác theo thứ tự ngược khi thất bại):

  • •Tạo người dùng Linux (vos_<order_number>, trong giới hạn 32 ký tự, giữ nguyên chữ hoa/thường)
  • •Cấu trúc thư mục: /var/www/customers/<order>/{public_html,logs,tmp} (chmod 750/2775/750/1770)
  • •Hạn ngạch đĩa (setquota -u <user> <soft> <hard>, hard = soft × 1.1)
  • •Kiểm tra xung đột thư mục: từ chối nếu xung đột với nginx vhost / reserved_subdomains hiện có
  • •Gắn kết SSD 1,9TB /var/www (ext4 + noatime + usrquota,grpquota)
  • •Sudoers trung tâm (/etc/sudoers.d/voscms-hosting-provisioner) — www-data chạy các lệnh root (useradd/setquota/nginx v.v.) không cần mật khẩu (NOPASSWD)
  • •Hạn chế mẫu đối số theo lệnh (vos_, /var/www/customers/, *.conf) — vượt qua xác thực visudo

Công cụ CLI scripts/provision-hosting.php:

php provision-hosting.php SVC260428AE7476 hotel.com 1GB
php provision-hosting.php --order SVC260428AE7476           # tự động tra cứu DB
php provision-hosting.php --deprovision SVC260428AE7476 hotel.com
php provision-hosting.php --install-voscms <order> <domain> <capacity>

Mẫu config/templates/:

  • •nginx-vhost.conf.tpl — HTTP + vị trí thách thức ACME + socket FPM theo người dùng
  • •welcome.html.tpl — trang chào mừng kích hoạt

Added

Mỗi hosting chạy PHP dưới người dùng riêng (ngăn chặn xâm phạm liên trang) + SSL tự động được cấp ngay cả phía sau proxy Cloudflare.

config/templates/php-fpm-pool.conf.tpl:

  • •user = vos_<order> / group = www-data — cách ly UID
  • •listen = /var/run/php/<order>.sock — socket theo người dùng
  • •pm = ondemand — tiết kiệm bộ nhớ cho hosting lưu lượng thấp
  • •php_admin_value[open_basedir] — giới hạn truy cập vào thư mục trang + /tmp + /usr/share/php
  • •disable_functions — exec, passthru, shell_exec, system, proc_open, popen, pcntl_exec
  • •session.save_path / upload_tmp_dir — cách ly vào thư mục người dùng
  • •env: HOSTING_ORDER / HOSTING_USER / HOSTING_DOMAIN

SSL Let's Encrypt — thách thức Cloudflare DNS-01:

  • •Plugin python3-certbot-dns-cloudflare
  • •/etc/letsencrypt/cloudflare/credentials.ini (root 0600, CLOUDFLARE_API_TOKEN từ .env)
  • •Cấp bất kể proxy Cloudflare / khả năng tiếp cận bên ngoài
  • •Khối máy chủ HTTPS được thêm tự động (TLS 1.2/1.3, mã hóa mạnh, HSTS, X-Frame-Options, X-Content-Type-Options)
  • •Tự động chuyển hướng HTTP → HTTPS 301
  • •certbot.timer tự động gia hạn hai lần mỗi ngày (đã hoạt động)

Added

Cách ly DB + người dùng theo từng đơn hàng hosting.

  • •Tài khoản MySQL hosting_admin (tạo một lần, ALL PRIVILEGES + GRANT OPTION) — chỉ dành cho quản lý DB
  • •Tên DB/người dùng = vos_<order> (giống tên người dùng Linux)
  • •Mật khẩu: 32 hex ngẫu nhiên (bin2hex(random_bytes(16)))
  • •GRANT ALL PRIVILEGES ON vos_<order>.* TO vos_<order>@localhost — chỉ truy cập DB của mình
  • •Xác minh cách ly: truy cập DB hosting khác / voscms_prod trả về Access denied 1044

Tự động cài đặt VosCMS (installVoscms() — kích hoạt bởi --install-voscms hoặc khi addon có install_info):

  • •Giải nén voscms-dist/voscms-X.Y.Z.zip mới nhất → public_html
  • •Tự động tạo .env: APP_KEY=base64:<32 bytes> / thông tin DB / HOSTING_ORDER được chèn
  • •Quyền: vos_:www-data, .env chmod 640
  • •Gọi install-core.php không đầu (hiện có vấn đề chuyển hướng 301, sẽ giải quyết cùng Giai đoạn 4)

Verified

provision DEMO260429FULL demo07.21ces.com 1GB --install-voscms:

  • •✅ Người dùng vos_DEMO260429FULL (cách ly UID, nhóm www-data)
  • •✅ Hạn ngạch đĩa 1GB soft / 1,05GB hard
  • •✅ PHP-FPM pool socket riêng
  • •✅ nginx vhost (HTTP + HTTPS, HSTS)
  • •✅ SSL Let's Encrypt (/etc/letsencrypt/live/demo07.21ces.com/)
  • •✅ MySQL DB vos_DEMO260429FULL + người dùng (cách ly đã xác minh)
  • •✅ File VosCMS 2.3.9 + .env đã triển khai

deprovision: Tất cả tài nguyên được xóa sạch (người dùng/home/DB/FPM pool/nginx/SSL).

v2.4.0 2026-04-29 · 6 tháng trước
Cơ sở hạ tầng tự động hóa hosting + Thanh toán theo lịch + Hệ thống mail hoàn thiện

Added

Thay vì phương thức tính phí anniversary tiêu chuẩn ngành (từ ngày đăng ký đến cùng ngày một năm sau), nay chuyển sang phương thức chốt cuối tháng theo lịch (từ ngày 1 tháng sau đến ngày cuối tháng hết hạn). Người dùng đăng ký cùng tháng có chung ngày hết hạn, đơn giản hóa việc xử lý hàng loạt cron và chốt sổ kế toán. Theo mô hình chuẩn hosting Nhật Bản (月末締め翌月1日請求).

  • •DB: thêm cột rzx_subscriptions.billing_start DATETIME NULL (ngày bắt đầu tính phí bình thường)
  • •Helper: _proratedFirstAmount (đơn giá tháng ÷ 30 × số ngày còn lại), _calendarBillingStart (ngày 1 tháng sau), _calendarExpires (ngày cuối 23:59:59)
  • •Đơn hàng: tự động thêm hosting_prorated vào khoản thanh toán hosting (ví dụ: đăng ký 2/4, 12 tháng ¥1.000/tháng → tháng đầu ¥967 + 12 tháng bình thường ¥12.000 = ¥12.967)
  • •Tên miền giữ nguyên tính phí anniversary (chu kỳ đăng ký 1 năm); hosting, mail, bảo trì và dịch vụ bổ sung dùng phương thức lịch
  • •Xử lý -1 second → -1 day trong service-order.php cũng được thống nhất
  • •Dịch vụ bổ sung (thêm dung lượng web) cũng dùng cách tính phí theo ngày + tổng N tháng bình thường, tự động đồng bộ với ngày hết hạn hosting

Added

Cài đặt Postfix + Dovecot + Rspamd + Roundcube + OpenDKIM + Let's Encrypt trên ConoHa VPS (133.117.72.149). mail-tester 10/10, FCRDNS được xác minh. Tự động thiết lập tên miền khi đặt hàng.

  • •Đăng ký DNS tự động (CloudflareDns.php) — A / MX / SPF / DKIM / DMARC 5 bản ghi cùng lúc
  • •Tạo khóa DKIM — mx1 SSH rspamadm dkim_keygen (khóa ed25519 chuyên dụng storage/keys/mailsync_ed25519, sở hữu bởi www-data, 0700)
  • •Cấp phát 3 chế độ (MailDomainProvisioner.php): free (tên miền phụ ngay lập tức) / new (đã mua tên miền, admin kích hoạt) / existing (hướng dẫn đổi NS). Máy trạng thái: existing_pending / new_pending / active
  • •Mật khẩu: SHA512-CRYPT ({SHA512-CRYPT}$6$...) — hash một chiều tương thích Dovecot. Script di chuyển mật khẩu enc: cũ (hàm encrypt): scripts/migrate-mail-passwords.php
  • •Cron đồng bộ mx1 (scripts/mail-sync-to-mx1.php) — voscms_prod → mx1 mail_lookup virtual_users mỗi 5 phút. Bộ kích hoạt tức thì (triggerMailSyncToMx1()) cho đồng bộ nền ngay sau hành động mail
  • •Đăng ký cron tự động: /etc/cron.d/voscms-mail-sync
  • •Thông báo: mẫu mail HTML cho admin (cần cấp phát) / khách hàng (mail sẵn sàng) (MailNotifier.php)

Added

Quản lý mail cơ bản / mail doanh nghiệp gộp với hosting. Sửa lỗi hiển thị trùng lặp khi cùng một địa chỉ được lưu ở cả mail subscription và metadata hosting (nguồn sự thật duy nhất: mail subscription).

  • •Nút webmail — tham số GET ?_user=địa_chỉ của Roundcube để điền sẵn tên đăng nhập, target="_blank". Thứ tự ưu tiên URL: metadata.mail_server.webmail_url → env WEBMAIL_URL → mặc định https://mail.voscms.com/
  • •Nút đổi email — để sửa lỗi nhập. Tên miền cố định; chỉ phần local thay đổi. Tất cả metadata mail + hosting của cùng đơn hàng được đồng bộ
  • •Logic loại trùng (mail.php) — _seenAddresses chỉ hiển thị mỗi địa chỉ một lần, mail subscription được ưu tiên
  • •Chuyển đổi virtual hosting → mail trong service-detail.php chỉ chạy khi không có mail subscription thực (tương thích dữ liệu cũ)
  • •service-order.php không còn lưu hosting metadata.mail_accounts cho đăng ký mới (mail subscription là nguồn duy nhất)

Added

Mua thêm dung lượng lưu trữ với thanh toán trong tab dịch vụ bổ sung của trang cá nhân. Đăng ký khách hàng PAY.JP + chargeCustomer.

  • •Modal: chọn dung lượng (1 GB / 3 GB / 5 GB) + nhập thông tin thẻ (payjp.js v2 Elements)
  • •Đăng ký thẻ / thanh toán bằng thẻ khác / quay lại thẻ đã đăng ký — chuyển đổi
  • •Tự động phát hiện thẻ hết hạn/bị từ chối (expired_card, card_declined, invalid_* v.v. mã lỗi PAY.JP) → form thẻ tự động mở + banner hướng dẫn
  • •Thêm trường nhập tên chủ thẻ (addon-card-holder) — lưu dưới dạng metadata khách hàng, không đưa vào token (PAY.JP v2 Elements không hỗ trợ tùy chọn name)
  • •Mẫu Portal: document.body.appendChild() để thoát khỏi container bị ràng buộc transform và phủ toàn viewport (z-[9999])
  • •Nếu charge thất bại sau khi tạo khách hàng mới: tự động hoàn tiền + xóa khách hàng (ngăn bản ghi mồ côi)
  • •hosting metadata.extra_storage[] được tích lũy; thanh dung lượng trong tab hosting hiển thị tổng kết hợp

Added

Cấu trúc 14 điều khoản (định nghĩa, đăng ký, phí, tự động gia hạn, hủy, dịch vụ, sao lưu, sử dụng bị cấm, tạm ngừng, bảo trì, quyền riêng tư, trách nhiệm, thay đổi, thẩm quyền) tham khảo điều khoản chuẩn của các nhà cung cấp hosting Nhật Bản như StarServer. Quy định rõ phương thức tính phí theo lịch + tính phí theo ngày cho tháng đầu + hoàn tiền các tháng chưa sử dụng khi hủy.

  • •Đăng ký trang hệ thống: config/system-pages.php slug hosting-terms, 🖥️ chàm
  • •Ánh xạ trình soạn thảo trang: pages-document.php — pageMetaMap['hosting-terms']
  • •Dữ liệu mẫu DB: ja (chính) / ko / en — 3 ngôn ngữ (rzx_page_contents)
  • •i18n: site.pages.hosting_terms + hosting_terms_edit (editor_title/desc)

Added

  • •4 tab luôn hiển thị (detail.php) — hosting/domain/mail/addon. Hiển thị thông báo trạng thái rỗng (empty_*) khi không có dữ liệu
  • •Tab dịch vụ bổ sung — nút + Thêm Dung lượng (modal cấp miễn phí của admin; chọn dung lượng ngay lập tức tạo addon subscription active, billing_amount=0, expires=ngày hết hạn hosting) + nút thùng rác/xóa theo từng mục (xóa mềm status=cancelled, xóa khỏi hosting metadata.extra_storage[])
  • •Danh sách — cải thiện hiển thị người nộp đơn (index.php) — các đơn hàng của quản trị viên hệ thống có role supervisor/admin được hiển thị dạng user.name + phụ đề màu tím Siêu quản trị viên: [email protected] (tránh lỗi giải mã applicant_name cũ đã mã hóa như FKzGx9SE7xG/2)
  • •Nút tạo đơn hàng (+ New Order) — chỉ UI, chức năng sẽ thêm sau
  • •i18n 13 ngôn ngữ: role_supervisor, role_admin, btn_create_order, empty_, btn_add_storage_addon, btn_delete_addon, modal_add_storage_, confirm_, alert_ và hơn 20 khóa

Added

  • •subdomain-check.php — ưu tiên DB (reserved_subdomains) + fallback API Cloudflare. JS checkSubdomain() gọi server và phản ánh kết quả
  • •Tái xác thực phía server trong service-order.php ngay trước khi thanh toán — ngăn bypass phía client
  • •Tự động nhập reserved_subdomains — 11 bản ghi hiện có từ zone Cloudflare (vos/bestatech/bt/dev/ec430/ec431/salon/ssh/test/thevos/ai.21ces.com)
  • •Sửa lỗi INSERT IGNORE của menu (menus-api.php):
  • •add_menu_item: dọn dẹp bản dịch cũ ngay sau INSERT + ghi đè bằng INSERT ... ON DUPLICATE KEY UPDATE
  • •update_menu_item: phát hiện thay đổi title/url, xóa 13 bản dịch cũ + đăng ký lại nếu là trang hệ thống
  • •rename_menu_item: dọn dẹp bản dịch cũ khi đổi tiêu đề
  • •Sửa hồi quy nơi menu cũ (id=38, "Giới thiệu VosCMS") trỏ đến menu điều khoản hosting mới

Added

Xây dựng luồng: đặt hàng dịch vụ → thanh toán hoàn tất → tự động cấp phát tên miền mail → thông báo khách hàng.

  • •Thêm lời gọi _autoProvisionMailDomain() trong service-order.php — chạy bên ngoài transaction thanh toán (cách ly tính toàn vẹn DB)
  • •DB: rzx_reserved_subdomains (zone, subdomain, record_type, reserved_by, reason) — cache khả dụng
  • •Khóa DKIM tự động tạo, lưu vào metadata.mail_provision dưới dạng mode/origin/domain/zone/subdomain/provisioned_at
  • •Phân nhánh UI theo chế độ cấp phát (service-detail.php): pending / new_pending / existing_pending — ẩn các tab, chỉ hiển thị màn hình theo dõi (_setup-monitor.php); tab chỉ hiện khi ở trạng thái active

Fixed

$arr['key'] ?? [] của PHP trả về giá trị tạm thời nên &$ref không ảnh hưởng đến mảng gốc. change_mail_password / change_mail_address trả về phản hồi thành công nhưng UPDATE metadata không có tác dụng — thay đổi mật khẩu và địa chỉ đều thất bại âm thầm.

  • •Chuyển sang mẫu cập nhật trực tiếp theo chỉ số: foreach ($arr as $i => $item) { $arr[$i]['k'] = ... }
  • •Lưu mật khẩu mail mới trong service-order.php cũng đổi từ encrypt() (hai chiều) sang mail_password_hash() (SHA512-CRYPT)

Fixed

  • •Màu xanh huỳnh quang sáng trong tóm tắt thanh toán → màu sắc tươm tất hơn: text-green-400 → text-green-600 dark:text-green-400 (7 vị trí)
  • •Thiếu khóa i18n trong thông báo phản hồi kiểm tra tên miền phụ (ánh xạ PHP→JS i18n trong order.php + thống nhất placeholder :fqdn)
  • •Sửa tính toán ngày hết hạn: +N months -1 second (cùng ngày) → +N months -1 day (trước đúng 1 ngày) → cuối cùng thống nhất sang phương thức lịch

Database

  • •Thêm rzx_subscriptions.billing_start DATETIME NULL (dev + prod)
  • •Bảng rzx_reserved_subdomains (cache xung đột zone Cloudflare)
  • •rzx_page_contents được nạp dữ liệu hosting-terms (ja/ko/en)
v2.3.9 2026-04-27 · 6 tháng trước
i18n Đặt Hàng Dịch Vụ + Hệ Thống Menu 3 Vùng

Added

Toàn bộ văn bản trong 6 khu vực (tên miền, hosting, tiện ích bổ sung, người đăng ký, thanh toán, tóm tắt) và trang hoàn tất thanh toán đã được dịch sang 13 ngôn ngữ. Văn bản alert/modal phía client được đưa vào từ PHP qua mẫu var I18N = {...} + t(key, replace).

  • •Vị trí: plugins/vos-hosting/lang/{13 locales}/services.php — services.order.* hơn 200 khóa
  • •Chi tiết dịch vụ trang của tôi: services.detail.* hơn 70 khóa, service-detail.php
  • •Quản lý đơn hàng admin: services.admin_orders.* hơn 115 khóa, admin/service-orders/
  • •Nhãn tiếng Hàn lưu trong DB (gói hosting, bảo trì, tiện ích bổ sung) được ánh xạ theo ID cài đặt qua closure _localizeLabel($sub) và áp dụng db_trans() → xử lý nhất quán ở trang của tôi và admin

Added

Khi nhấn nút thanh toán, chi tiết đơn hàng (tên miền/gói/tiện ích bổ sung/người đăng ký/điều khoản) được kiểm tra và modal tóm tắt hiển thị → người dùng xác nhận → tiến hành thanh toán. Ngăn ngừa các lỗi như đăng ký tên miền phụ trống.

  • •order.js — showOrderConfirmModal(), closeOrderConfirmModal(), confirmAndPay()
  • •Tăng cường xóa các lớp modal còn lại sau khi hoàn tất thanh toán (xóa DOM + reset overflow body/documentElement)

Added

Khi chọn "Hỗ trợ cài đặt" (_id='install') trong tiện ích bổ sung, hiển thị form nhập ID admin/email/mật khẩu/tên trang web. Mật khẩu được che + toggle biểu tượng mắt + thông báo "thay đổi sau khi cài đặt". Giá trị được lưu dưới dạng install_info trong metadata đăng ký, hiển thị ở trang của tôi và admin.

  • •Nhập: _addons.php
  • •Hiển thị: trang của tôi/admin partials/addon.php (hộp nền xanh + toggle mật khẩu)

Added

Ghi chú gắn với tab tiện ích bổ sung đã được chuyển lên mức đơn hàng (rzx_orders.admin_notes). Luôn hiển thị dưới dạng textarea 7 dòng phía trên nhật ký hoạt động bên phải, bất kể có tiện ích bổ sung hay không. Thêm hành động AJAX update_order_memo.

Added

Trường section (top/main/bottom, mặc định main) được giới thiệu để phân tách menu core và menu plugin về mặt trực quan. Dải phân cách được tự động chèn giữa các vùng; nếu không có menu nào hiển thị được trong một vùng, toàn bộ vùng bao gồm dải phân cách sẽ bị bỏ qua.

Thanh bên admin:

  • •top: Bảng điều khiển / Quản lý thành viên / Quản lý trang / Trình cài đặt tự động (vos-autoinstall)
  • •main: Giấy phép VosCMS (vos-license-manager) / Quản lý hosting (vos-hosting)
  • •bottom: Plugin / Cài đặt
  • •Thay đổi: config/admin-menu.php, admin-sidebar.php

Thanh bên trang của tôi:

  • •top: Bảng điều khiển / Hồ sơ / Tin nhắn
  • •main: Dịch vụ (vos-hosting tự động thêm) — tự động tích lũy khi các plugin khác thêm mục
  • •bottom: Cài đặt / Mật khẩu / Xóa tài khoản / Đăng xuất
  • •Thay đổi: config/mypage-menu.php, mypage-sidebar.php

Đăng ký menu plugin: các trường section + position trong mục menus.admin / menus.mypage của plugin.json xác định vùng. Menu services đã được chuyển từ core mypage-menu.php → vos-hosting/plugin.json (đăng ký tự động).

Added

API xác thực giấy phép và API cổng thông tin nhà phát triển ở trong core, nghĩa là sẽ bị lộ ra trên tất cả các trang voscms được triển khai. Cả hai API đã được tách vào một plugin mới chỉ dành cho trụ sở.

  • •vos-license-server (scope: hq_only): chuyển 7 endpoint giấy phép (check, register, verify, stats, updates, register-plugin, _init)
  • •vos-developer (scope: hq_only): chuyển 7 endpoint cổng nhà phát triển (register, login, submit, my-items, earnings, update-version, _init)
  • •api/_plugin_dispatch.php — wrapper core kiểm tra rzx_plugins.is_active trước khi dispatch; trả về 404 nếu không hoạt động
  • •Core /api/license/.php và /api/developer/.php chỉ giữ lại wrapper (duy trì tương thích bên ngoài)
  • •/api/notices.php với whitelist env HQ_HOSTS được thêm (chỉ phản hồi từ domain HQ voscms.com)
  • •Script build (build-voscms.sh) đã loại trừ api/license, api/developer, api/notices.php và vos-license-manager

Fixed

  • •Lỗi hết hạn hợp đồng hosting +1 ngày (+12 months → +12 months -1 second) — áp dụng ở 4 nơi: subscription/free/paid/bank
  • •Email doanh nghiệp: không thể thêm 2 hoặc nhiều hơn (bộ chọn đang bắt nút X)
  • •Tóm tắt đơn hàng: dung lượng bổ sung không được tổng hợp (thiếu thuộc tính name trên select lưu trữ)
  • •Nhãn gói hosting chưa được bản địa hóa — giải quyết bằng cách khớp service_hosting_plans._id với db_trans()
v2.3.8 2026-04-25 · 6 tháng trước
Hoàn thiện đa ngôn ngữ bảng tin + skin FAQ/Q&A

Added

_init.php giờ truy vấn trực tiếp rzx_translations cho board.{id}.{title|description|header_content|footer_content|seo_keywords|seo_description} (locale hiện tại → en → nguồn). Trên bất kỳ trang nào — list/read/write/settings — $board[$field] tự động được điền bằng giá trị đã dịch. Nút "← Quay lại" trên trang cài đặt bảng tin cũng được dịch tự động theo cùng cơ chế.

Seed 13 ngôn ngữ cho title + header_content của bảng tin vấn đề (id=6) — cấu trúc HTML được giữ nguyên, chỉ dịch văn bản, huy hiệu giai đoạn xử lý cũng hiển thị theo từng ngôn ngữ. Script seed: scripts/seed_issue_i18n.php + scripts/seed_issue_i18n_data.php.

Added

Dịch các định nghĩa (nhãn/mô tả/tùy chọn/giá trị mặc định) của rzx_board_extra_vars sang 13 ngôn ngữ. 4 trường × 13 = 52 hàng.

  • •ExtraVarRenderer::renderAll($vars, $values, $mode, $boardId) — thêm đối số boardId, applyDefTranslations() tải hàng loạt tất cả bản dịch biến trong một truy vấn duy nhất.
  • •ExtraVarRenderer::getOptionLabel($boardId, $varName, $value) — tra cứu nhãn đã dịch của một tùy chọn cho chế độ xem danh sách (bộ nhớ cache tĩnh).
  • •renderStatusBadge($value, $size, $displayLabel = null) — màu sắc sử dụng ánh xạ nguồn (ko), chỉ dịch văn bản → màu nhất quán trên tất cả ngôn ngữ (đã tiếp nhận = hồng, đã giải quyết = ngọc lục bảo).
  • •select/radio/checkbox: mẫu value=nguồn / label=đã dịch. Giá trị nguồn luôn được lưu khi đăng bài, đảm bảo tương thích dữ liệu.
  • •Cập nhật điểm gọi: read.php, write.php, _list-row.php, _list-card/_list-webzine/_list-gallery của skin mặc định.

Seed 13 ngôn ngữ cho biến phụ trợ status của bảng tin vấn đề: scripts/seed_ev_status_i18n.php.

Added

API extra_var_get trả về các giá trị đã dịch cho locale hiện tại dưới dạng đối tượng localized thông qua db_trans(). Modal JS ưu tiên hiển thị localized.title || ev.title → ở chế độ tiếng Nhật, mở modal sẽ tự động hiển thị "処理ステージ".

extra_var_update phân nhánh theo locale:

  • •Locale nguồn (ko) → cập nhật toàn bộ hàng nguồn (hành vi hiện tại)
  • •Locale không phải nguồn (ja/en/…) → chỉ lưu meta (var_type/quyền/3 hộp kiểm) vào nguồn; lưu 4 trường dịch (title/description/options/default_value) vào rzx_translations theo locale hiện tại → đảm bảo tính toàn vẹn nguồn

Tên hiển thị trong danh sách biến phụ trợ cũng dùng db_trans('board_ev.{boardId}.{varName}.title').

Added

Phần "Quyền chỉnh sửa" (nhãn/tùy chọn dropdown/văn bản trợ giúp) của modal chỉnh sửa biến phụ trợ được tách thành các file lang 13 ngôn ngữ. Khóa mới: site.boards.ev_permission, ev_perm_all, ev_perm_member, ev_perm_admin, ev_permission_help.

Added

Chuẩn hóa hai chiều cho trường "Tùy chọn" trong modal chỉnh sửa biến phụ trợ:

  • •Tải modal: chuyển đổi mảng JSON từ DB (["a","b","c"]) sang định dạng ngắt dòng để hiển thị trong textarea (phù hợp với hướng dẫn)
  • •API lưu: helper ev_normalize_options() chấp nhận cả đầu vào ngắt dòng hoặc JSON và lưu nhất quán dưới dạng mảng JSON. Sửa lỗi trước đây đầu vào ngắt dòng được lưu dưới dạng NULL.

Added

Hai skin mới cho các mẫu nội dung ngoài vấn đề/thông báo.

FAQ (skins/board/faq/) — bài đăng = câu hỏi, nội dung = câu trả lời. Bao gồm thanh tìm kiếm, bộ lọc danh mục và phân trang. Bật/tắt hiển thị khu vực tiêu đề, tiêu đề/phụ đề đa ngôn ngữ, hỗ trợ nền (hình ảnh/video/không có), điều chỉnh độ mờ lớp phủ. v1.0.1.

Q&A (skins/board/qna/) — bài đăng = câu hỏi (tiêu đề+nội dung), bình luận = câu trả lời. Huy hiệu chưa trả lời, mục đầu tiên tự động mở rộng, hiển thị bình luận theo cây (parent_id/depth). Trả lời cho trả lời được thụt lề + nhãn "↳ Trả lời" (cấp cao nhất = "A."). Form chỉnh sửa/trả lời inline (chỉ tác giả/admin có thể chỉnh sửa, quyền perm_comment để trả lời). v1.0.0.

Cả hai skin dùng chung: biểu tượng bánh răng cài đặt admin được đặt ở góc dưới bên phải thanh tìm kiếm (tách khỏi khu vực tiêu đề). boardSkinFile() hoạt động với ưu tiên _list-full.php.

Added

Thêm action update vào api-comments.php. Chỉ comment.user_id == người dùng hiện tại hoặc admin mới có thể chỉnh sửa. Sau khi xác thực số ký tự, cập nhật content + updated_at.

Added

Token {year} trong trường copyright của cài đặt layout tự động được thay thế bằng năm hiện tại khi render. DB giữ nguyên bản gốc (có {year}) nên không bao giờ cần cập nhật thủ công. Áp dụng cho: default/minimal/modern/base-footer.php. Mô tả bản quyền trong 4 file layout.json được mở rộng sang 13 ngôn ngữ, với hướng dẫn sử dụng {year} hiển thị bằng từng ngôn ngữ bản địa.

Cũng sửa lỗi $_lc['copyright'] bị bỏ qua trong footer default/minimal — giờ giá trị cài đặt layout thực sự được render.

Added

Seed 13 ngôn ngữ cho menu_item.38.title (Giới thiệu VosCMS / About VosCMS / VosCMSについて / Über VosCMS / Acerca de VosCMS / À propos de VosCMS / Tentang VosCMS / VosCMS-ийн тухай / О VosCMS / VosCMS Hakkında / Giới thiệu VosCMS / 关于 VosCMS / 關於 VosCMS).

Added

Một mẫu cho mỗi giai đoạn xử lý + 1 mẫu đã giải quyết = tổng 4. Dịch tiêu đề/nội dung của mỗi bài đăng sang 13 ngôn ngữ (104 hàng).

Giai đoạnTiêu đề (ko)Trạng thái
Đã tiếp nhận[Lỗi] Nút X menu hamburger trên di động không hoạt độngMới
Đang xem xét[Yêu cầu tính năng] Thông báo email cho tác giả bài khi có bình luậnMới
Đang xử lý[Hiệu năng] Cải thiện tốc độ tải lần đầu trang chi tiết marketplaceMới
Đã giải quyếtHình ảnh đính kèm trong bài đăng bảng tin được chèn vào nội dung...Hiện có

Đã xóa bài đăng 34 hiện có (bài đăng thử nghiệm với style inline Tailwind tích lũy).

Fixed

customer/board/list.php require helper rzx_admin_icons ở dòng 167, nhưng include file skin ở dòng 161 đã thoát bằng return — gây lỗi 500 khi rzx_admin_icons() được gọi trong skin FAQ/Q&A. Đã chuyển require_once lên trước include skin.

v2.3.7 2026-04-25 · 6 tháng trước
AutoInstall UX Integrated Overhaul

Changed

Xóa các tham chiếu còn sót lại đến tên cũ /marketplace. Sửa lỗi form tìm kiếm gửi GET đến /marketplace gây chuyển hướng về dashboard (rời khỏi trang khi thay đổi tìm kiếm/sắp xếp/bộ lọc). Thống nhất toàn bộ browse.php, item-detail.php, item-submit.php, purchases.php và assets/js/marketplace.js sang /autoinstall.

Added

Ở Bước 4 của install.php, thêm gợi ý màu vàng bên dưới ô nhập đường dẫn admin, xem trước URL theo thời gian thực và hướng dẫn có thể mở rộng "Tại sao nên thay đổi?". Ba lý do được giải thích bằng ngôn ngữ dễ hiểu với mọi người: các cuộc tấn công tự động (brute force), quét lỗ hổng bảo mật và giới hạn của mật khẩu mạnh. Áp dụng cho tất cả 13 ngôn ngữ.

Added

Ở bước hoàn tất cài đặt của install.php, plugin vos-autoinstall được tự động đăng ký và kích hoạt (bằng cách gọi trực tiếp PluginManager::install()). Người dùng có thể dùng marketplace ngay khi vào trang quản trị mà không cần bước cài đặt riêng.

Added

Thêm hỗ trợ tham số ?locale=xx cho market.21ces.com/api/market/catalog và /item. JSON đa ngôn ngữ của name, description, short_description, cat_name được trả về từ server dưới dạng một chuỗi duy nhất (dự phòng: locale yêu cầu → en → giá trị đầu tiên). Xóa toàn bộ logic json_decode + locale fallback trùng lặp ở phía VosCMS (browse.php, item-detail.php, _components/item-card.php).

Added

Tích hợp quản lý TTL của cache phản hồi API marketplace (dựa trên file) vào cài đặt PluginManager. Mã cứng 30 phút → mặc định 5 phút, tùy chọn 1/5/10/30/60 phút. Cả phần cache marketplace trong https://vos.21ces.com/theadmin/settings/general và /theadmin/autoinstall/settings đều đọc và ghi cùng một cài đặt, tự động đồng bộ. Thêm nút làm mới cache ngay lập tức trên trang AutoInstall và trang cài đặt chung. Cache hiện có tự động bị vô hiệu hóa khi đổi TTL.

Added

Hiển thị cùng bảng như admin marketplace (loại dữ liệu / mô tả ngắn / slug / Product Key / phiên bản VosCMS và PHP tối thiểu / đối tác / giá / giấy phép) ngay sau phần header. Thay đổi tỷ lệ nội dung trái:phải từ 2:1 thành 3:1 để mở rộng vùng nội dung.

Added

Nút "Viết đánh giá" ở góc trên phải của tab đánh giá trên trang chi tiết. Modal nhập xếp hạng sao / biệt danh / nội dung → API VosCMS → chuyển tiếp đến marketplace POST /api/market/item/review. Khóa cấp phép VosCMS + tên miền đính kèm tự động, giới hạn một lần gửi mỗi tên miền, người mua tự động nhận is_verified=1. Đánh giá được lưu trong DB marketplace (rzx_mkt_reviews) với status='pending' và xuất bản sau khi operator phê duyệt. Endpoint mới GET /api/market/item/reviews?slug=... chỉ trả về đánh giá đã được duyệt. Tên miền được che một phần (mys***.com).

Added

Hộp kiểm Chỉ miễn phí trước đây → mở rộng thành toggle 3 trạng thái Tất cả / Miễn phí / Trả phí. Thêm tham số paid=1 vào API catalog thị trường (i.price>0). Tách ra khỏi thanh tìm kiếm, chuyển lên trước vùng toggle chế độ xem, tích hợp với bộ chọn sắp xếp thành thanh công cụ header.

Changed

Viền input tìm kiếm border-2 border-emerald-300, hộp nền xanh lá ở biểu tượng tìm kiếm bên trái, nút tìm kiếm bg-emerald-500. Đơn giản hóa thanh tìm kiếm chỉ giữ lại ô nhập từ khóa; tính năng sắp xếp và lọc chuyển sang header phần thân.

Changed

Trạng tháiHiển thị
Miễn phíCài đặt + Tải xuống
Trả phí (chưa mua)Mua (modal thanh toán PAY.JP của marketplace)
Trả phí (đã mua)Cài đặt + Tải xuống
Đã cài đặt"Đã cài đặt"

Cùng phân nhánh áp dụng cho 4 chế độ xem trang danh sách (list/webzine/card/grid). Tập hợp slug đã mua được truy vấn một lần khi vào trang và tái sử dụng. Thanh toán được xử lý bởi marketplace POST /api/market/item/purchase, thực hiện billing PAY.JP + cấp phép.

Changed

  • •Toggle kiểu xem: bỏ nhãn chữ → chỉ còn biểu tượng + title / aria-label (duy trì khả năng tiếp cận)
  • •Huy hiệu loại: nền sáng bg-<color>-100 → nền tối mờ bg-zinc-900/85 backdrop-blur-sm + chữ màu (cải thiện khả năng đọc trên ảnh)
  • •Phần ảnh chụp màn hình: từ ngay sau header → di chuyển xuống dưới nội dung tab, hiển thị số lượng (n) như marketplace
  • •dark:prose-invert trên trang chi tiết không hoạt động → thêm plugin typography vào CDN Tailwind
  • •Vùng mô tả trang chi tiết: cùng cách với admin marketplace — render markup HTML nguyên vẹn, chỉ loại bỏ các phần tử nguy hiểm như <script>/<iframe>/<style>/onXX

Fixed

  • •Form thẻ PAY.JP không nhận input: được mount trước khi hiển thị trong trạng thái ẩn khiến iframe vẽ ở 0px. Giải quyết bằng khởi tạo lười + mount qua requestAnimationFrame
  • •Thiếu thumbnail widget: 28 widget đăng ký trong DB marketplace nhưng chỉ 12 widget miễn phí được sao chép vào /var/www/market/widgets/. Đồng bộ 14 cái còn thiếu. Thêm chuyển đổi URL tuyệt đối cho screenshots + tự động lọc file không tồn tại vào API catalog/item
  • •Cảnh báo plugin bundle không được ủy quyền: vos-autoinstall bị phát hiện là unauthorizedPlugins. Thêm hằng số BUNDLE_PLUGINS = ['vos-autoinstall', 'vos-marketplace'] vào LicenseStatus.php, áp dụng lọc trên tất cả active()/fromCache()/canUsePlugin(). Xử lý tương tự áp dụng cho máy chủ cấp phép verify.php
  • •Khả năng thêm widget trùng lặp: việc seed install.php chỉ dùng INSERT IGNORE nhưng rzx_page_widgets không có ràng buộc UNIQUE nên trùng lặp có thể xảy ra. Đổi thành DELETE FROM page_widgets WHERE page_slug='home' trước INSERT (không thêm ràng buộc UNIQUE vào DB vì có các trùng lặp có chủ ý với các trường hợp như widget bảng tin)

Migration Notes

  • •Menu/routes/migrations của plugin vos-autoinstall được tự động kích hoạt khi cài mới (các cài đặt hiện có cần kích hoạt một lần từ trang quản trị)
  • •TTL mặc định của cache API marketplace: 30 phút → 5 phút (để phản ánh nhanh hơn các thay đổi giá/nội dung)
  • •Cài đặt plugin vos-autoinstall.cache_ttl là mới
v2.3.6 2026-04-21 · 6 tháng trước
Tích Hợp API Marketplace Trực Tiếp

Changed

  • •browse.php: chuyển từ truy vấn DB nội bộ sang gọi API trực tiếp tới market.21ces.com/api/market/catalog
  • •item-detail.php: chuyển từ DB nội bộ sang gọi API /api/market/item và /api/market/item/versions
  • •CatalogClient.php: URL cơ sở API đổi từ /api/v1 → /api/market, trường phản hồi items[] → data[] được căn chỉnh

Fixed

Vấn đề: Khối áp dụng bố cục trong market.21ces.com/index.php thiếu xử lý trường hợp $__noLayout = true, khiến tất cả route API của plugin (api/market/*) trả về HTTP 200 + phản hồi rỗng.

Sửa lỗi: Thêm elseif ($__pageFile && $__noLayout) { include $__pageFile; } vào cuối index.php. api/market/catalog, api/market/item, api/market/updates/check, v.v. giờ hoạt động bình thường.

Added

Thêm tham số sort, free và featured vào plugins/vos-market/views/api/catalog.php, với các trường phản hồi mở rộng (sale_price, rating_avg, is_featured, v.v.).

Added

Helper mpApiFetch(): giảm thiểu yêu cầu đến máy chủ marketplace bằng bộ nhớ đệm file TTL 30 phút. Hiển thị banner lỗi khi phản hồi API thất bại.

v2.3.5 2026-04-21 · 6 tháng trước
Hoàn thiện logic đăng ký giấy phép tự động

Fixed

Vấn đề: Trong AdminRouter, sau khi tạo instance $licenseClient = new LicenseClient() và cố đăng ký tự động, cập nhật $_ENV['LICENSE_KEY'] không được phản ánh vào $this->licenseKey nội tại của instance — nên lệnh gọi check() trong cùng một request vẫn trả về unregistered.

Changed

  • •Khi vào check(), nếu $this->licenseKey trống, gọi ngay /api/license/register
  • •Nếu thành công: cập nhật $this->licenseKey + cập nhật $_ENV['LICENSE_KEY'] + lưu file .env, rồi tiến hành bước verify
  • •Chỉ trả về unregistered khi thất bại (server không phản hồi)
  • •Phương thức saveKeyToEnv() mới: thay thế dòng LICENSE_KEY= trống (trường hợp install.php thất bại) bằng key thực; bỏ qua nếu key hợp lệ đã tồn tại

Hiệu quả

  • •Người dùng cài thủ công không qua install.php → giấy phép được đăng ký tự động khi truy cập admin lần đầu
  • •Người dùng cập nhật từ phiên bản cũ (không có LICENSE_KEY) → tự động đăng ký khi truy cập admin lần đầu sau khi cập nhật
  • •Thông báo trên dashboard "Giấy phép chưa được đăng ký" giờ chỉ xuất hiện khi bản thân máy chủ giấy phép không khả dụng
v2.3.4 2026-04-20 · 6 tháng trước
Dọn dẹp ô nhiễm nội dung + Loại bỏ CSS kiểu thẻ

Fixed

File seed database/seeds/legal_pages.php chứa các biến CSS Tailwind (--tw-scale-x, --tw-pan-x, v.v., 400+) nhúng trực tiếp vào thuộc tính style="" của mọi thẻ <h1>/<h2>/<p>. Mỗi lần cài đặt, ô nhiễm này lan vào DB, khiến các trang terms và privacy bị phình to (đặc biệt privacy/ko đạt 128KB; bình thường chỉ 2KB).

  • •database/seeds/legal_pages.php: 442KB → 131KB (giảm 70%, cú pháp hợp lệ)
  • •Làm sạch 26 hàng đã bị ô nhiễm trong DB phát triển: 1,04MB → 56KB (xóa 988KB, −95%)
  • •scripts/clean-inline-styles.php mới — công cụ dọn dẹp hàng loạt style="... --tw-* ..." (có thể tái sử dụng nếu sự cố tái diễn)

Changed

CSS .board-content chứa các quy tắc ép buộc chuyển đổi mọi trang tài liệu bằng cách coi "h2 là tiêu đề thẻ và h2+p là nội dung thẻ". Điều này phá vỡ cấu trúc hero của các trang được thiết kế trực tiếp bằng Tailwind (ví dụ: Brand).

  • •Xóa 103 dòng quy tắc khối kiểu thẻ (149 → 45 dòng)
  • •Quy tắc còn lại: typography cơ bản (p/h·/blockquote/code/ul/ol/table), thẻ liên kết OG, ghi đè văn bản dark-mode
  • •Kết quả: khôi phục thiết kế gốc của trang Brand (h2 thanh xanh bên trái, hero căn giữa, v.v.)
  • •Tài liệu pháp lý (terms/privacy, v.v.) được phục vụ đầy đủ bởi typography chuẩn <h1><h2><p> — kiểu thẻ là trang trí quá mức
v2.3.3 2026-04-20 · 6 tháng trước
Hoàn Tác Cấu Trúc Dịch Thuật Trang (Trở Về Bảng Đơn)

Changed

Bối cảnh quyết định: Ở phiên bản 2.3.1 nội dung trang được tách thành rzx_page_contents cho bản gốc tiếng Hàn và rzx_translations cho các ngôn ngữ còn lại, và ở 2.3.2 đã bổ sung nhánh lưu riêng trong trình soạn thảo. Tuy nhiên, sau khi xem xét lại thiết kế, nhận thấy rằng hai bảng có cấu trúc về bản chất là giống nhau (slug/key + locale + content) nhưng lại gây ra các chi phí sau:

  • •Bản gốc tiếng Hàn được lưu trùng lặp ở cả hai bảng (cho việc phản chiếu chuỗi fallback db_trans)
  • •Logic lưu của trình soạn thảo cần phân nhánh ko vs. không phải ko
  • •Hiển thị trạng thái locale trong giao diện quản lý trang yêu cầu JOIN hai bảng
  • •Lý do ban đầu ("hàng đợi pipeline dịch thuật AI tích hợp") cũng không mang lại giá trị thực tế, vì nội dung trang dài HTML (10 KB) và chuỗi giao diện ngắn (20 byte) cần quy trình làm việc khác nhau (tách đoạn, bảo toàn thẻ, v.v.)

Cấu trúc được khôi phục: bảng đơn rzx_page_contents, một hàng mỗi locale (thiết kế ban đầu)

Migration

  • •rzx_translations.page.{slug}.title/content × 7 slug × 12 locale không phải ko (168 hàng) → khôi phục vào rzx_page_contents
  • •Xóa toàn bộ khóa page.* khỏi rzx_translations (234 hàng)
  • •Đối tượng: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
  • •Áp dụng cho cả database phát triển và sản xuất

Changed

  • •resources/views/admin/site/pages-edit-content.php — loại bỏ phân nhánh ko/không phải ko, UPSERT đơn giản
  • •resources/views/admin/site/pages-document.php — tương tự
  • •resources/views/customer/page.php — xóa db_trans('page.*.title/content'), đọc trực tiếp từ page_contents (chuỗi fallback locale → en → ko được giữ nguyên)
  • •resources/views/admin/site/pages.php — tiêu đề danh sách trang cũng đọc trực tiếp từ page_contents.title

Kept

Bảng rzx_translations được giữ nguyên — tiếp tục được dùng cho:

  • •Bảng tin (board_post.{id}.title/content)
  • •Chuỗi giao diện (menu.*, nhãn cài đặt)
  • •Meta SEO trang (page.{slug}.browser_title|meta_keywords|meta_description) — chuỗi ngắn, phù hợp ở đây

Nguyên tắc: chuỗi giao diện/meta ngắn → rzx_translations; nội dung thân trang dài → rzx_page_contents, lưu trữ tách biệt theo đặc tính của từng loại dữ liệu.

v2.3.2 2026-04-20 · 6 tháng trước
Căn chỉnh logic lưu bản dịch DB trong trình soạn thảo trang

Changed

Sau khi di chuyển cấu trúc lưu nội dung trang trong 2.3.1 sang ko gốc (rzx_page_contents) + DB dịch (rzx_translations), trình soạn thảo admin vẫn INSERT/UPDATE tất cả các locale chỉ vào rzx_page_contents — gây không khớp với định dạng di chuyển và truy vấn thất bại từ db_trans() phía render. Bản phát hành này sửa lỗi đó.

Quy tắc phân nhánh (locale nguồn = $_ENV['DEFAULT_LOCALE'] ?? 'ko'):

localeđích lưu
ko (nguồn)rzx_page_contents + phản chiếu sang rzx_translations (dự phòng cho db_trans())
en/ja/zh_CN/...chỉ rzx_translations (page.{slug}.title, page.{slug}.content)

Khi lưu locale không phải nguồn, nếu không có hàng nguồn trong rzx_page_contents, một hàng stub được tự động tạo (để giữ nguyên kết nối menu/cài đặt). is_active được áp dụng thống nhất cho hàng nguồn.

Changed

Khi mở trang chỉnh sửa locale không phải nguồn:

1. Tra cứu page.{slug}.title/content + locale từ rzx_translations trước

2. Dự phòng sang hàng rzx_page_contents cũ nếu không tìm thấy (tương thích với các trang bị bỏ sót khi di chuyển)

Với locale nguồn, chỉ dùng rzx_page_contents như trước.

Changed

  • •Xóa trang: cũng xóa rzx_translations WHERE lang_key LIKE 'page.{slug}.%'
  • •Đổi slug: UPDATE hàng loạt page.{old_slug}. → page.{new_slug}. trong rzx_translations.lang_key
v2.3.1 2026-04-20 · 6 tháng trước
Page Translation DB Migration + UI Cleanup + Logo Assets

Changed

Phương pháp trước đây lưu một hàng nội dung đầy đủ cho mỗi locale trong rzx_page_contents đã được thống nhất sang phương pháp ko gốc + DB dịch thuật (rzx_translations). Đảm bảo tính nhất quán cấu trúc với định dạng lưu trữ bảng tin (board_post.*).

7 trang mục tiêu: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy

Before:

rzx_page_contents
├── Brand / ko  (nội dung đầy đủ)
├── Brand / en  (nội dung đầy đủ)
├── ... (13 hàng locale)

After:

rzx_page_contents
└── Brand / ko  (1 hàng gốc)

rzx_translations
├── page.Brand.title   × 13 locale (bao gồm ko)
└── page.Brand.content × 13 locale

Kết quả di chuyển:

  • •rzx_page_contents: 7 slug × 12 hàng không phải ko = 84 hàng đã xóa
  • •rzx_translations: 7 slug × 13 locale × (title + content) = 182 hàng đã chuyển
  • •Áp dụng cho cả DB phát triển và sản xuất, kiểm tra render đạt yêu cầu (hiển thị đúng theo locale cho ko/en, v.v.)

Changed

  • •Nút "Trang mới" ở header đã xóa — chỉ là placeholder không hoạt động. Trang được tạo từ quản lý menu là nguồn sự thật duy nhất.
  • •Biểu tượng thùng rác 🗑 + handler AJAX + JS deleteUserPage() đã xóa — trang được dọn sạch khi xóa menu, nên không cần đường dẫn xóa trang độc lập. Ngăn menu bị hỏng do xóa nhầm.
  • •Giữ nguyên: biểu tượng cài đặt ⚙ · chỉnh sửa ✏ · xem trước 👁

Fixed

  • •Lỗi tải lên trong Cài đặt > Trang web > Hình ảnh logo: move_uploaded_file() thất bại âm thầm do thiếu thư mục con storage/logos/. Thêm tạo thư mục con tự động vào handler tải lên + tạo thư mục trên máy chủ phát triển và sản xuất (www-data:www-data, 775).
  • •Khôi phục ưu tiên logo bố cục: đã tạm đảo ngược thành "cài đặt trang web ưu tiên", sau đó khôi phục về bố cục > trang web dự phòng theo yêu cầu "logo riêng theo bố cục". Nếu bố cục không có logo, logo trang web sẽ được sử dụng tự động.
  • •Ảnh hưởng: skins/layouts/{default, minimal, modern, modern-copy-260413}/header.php và footer.php

Fixed

  • •Chỉ giữ hàng được tạo sớm nhất cho các slug trùng lặp bi-guide / logo-guide (id=186, 187), xóa các bản sao id=193, 194
  • •Áp dụng cho cả phát triển và sản xuất. Lỗi INSERT trùng lặp trong API menu đã được sửa từ v2.3.0

Added

Tài nguyên logo được tạo tại /var/www/_upload/ — tải lên sản xuất khi cần:

Biểu tượng (chỉ dấu hiệu)

  • •voscms-logo-color-{256,512,1024}.png · màu (deep·ocean·sky·ocean + deep ở giữa)
  • •voscms-logo-mono-{256,512,1024}.png · sky đơn sắc + gradient opacity 1/0.7/0.48/0.7

Wordmark ngang (cho header) — tỷ lệ 820×256

  • •voscms-wordmark-{128h,256h,512h}.png · sáng (Vos deep + CMS xám)
  • •voscms-wordmark-dark-{128h,256h,512h}.png · tối (Vos sky + CMS slate-300)

Wordmark dọc (cho biểu tượng ứng dụng / ảnh OG) — tỷ lệ 360×420

  • •voscms-stacked-light-{256h,512h,1024h}.png
  • •voscms-stacked-dark-{256h,512h,1024h}.png

Tất cả SVG gốc được bảo tồn. librsvg2-bin đã cài cung cấp CLI rsvg-convert. Vấn đề hỗ trợ màu OKLCH được giải quyết bằng phiên bản chuyển đổi hex (voscms-logo-mono-hex.svg).

v2.3.0 2026-04-20 · 6 tháng trước
Tái cấu trúc tab cài đặt trang + Hệ thống Changelog

Added

  • •Bảng DB rzx_changelog mới — bản ghi độc lập theo phiên bản × locale, theo dõi translation_source (original/ai/manual) + source_hash
  • •Trình phân tích RzxLib\Core\Changelog\ChangelogParser — chuẩn Keep a Changelog + danh sách trắng phần nội bộ (Infrastructure/Internal/Refactor/Chore/Docs/Test là riêng tư)
  • •Trình nhập ChangelogImporter — hợp nhất idempotent, bảo vệ bản dịch thủ công, phát hiện thay đổi qua content_hash
  • •Script CLI scripts/import-changelog.php — tùy chọn --file --locale --dry-run --silent, hỗ trợ SemVer pre-release (2.1.1-hotfix)
  • •Giao diện dịch thuật RzxLib\Core\Translate\{TranslatorInterface, NullTranslator, TranslatorFactory} — kích hoạt bằng cách thay đổi driver trong config/translator.php sau khi GPU Gemma 4 (ai.21ces.com) sẵn sàng
  • •Trang hệ thống /changelog được đăng ký (config/system-pages.php), giao diện front-end resources/views/system/changelog/index.php
  • •Skin chuyên dụng skins/page/changelog/skin.json — kiểu thẻ (filled/outlined/flat), màu theo từng phần, huy hiệu phiên bản, định dạng ngày, hiển thị thời gian tương đối, công tắc hiển thị phần nội bộ
  • •Trang chỉnh sửa /changelog/edit tách riêng — xem trước tải lên MD, ma trận phủ sóng đa ngôn ngữ, bật/tắt và xóa theo phiên bản, nút dịch AI (sắp ra mắt)
  • •Tự động hóa triển khai — bước 1.5/5 Changelog import được thêm vào deploy-voscms.sh: tự động phát hiện và hợp nhất file .md ko + 12 locale
  • •Khóa dịch site.pages.changelog được thêm cho 13 locale

Changed

  • •Thứ tự tab được sắp xếp lại: [Thông tin cơ bản] [Quyền] [Nâng cao] [Skin] — trang hệ thống có thể thêm tab riêng ở cuối
  • •Schema settings_tabs được giới thiệu (config/system-pages.php) — trang hệ thống khai báo mảng tab cấp cao nhất; mỗi mục được hiển thị động qua key/label/icon/view. Đã xóa legacy include dưới settings_view
  • •Nguyên tắc xác lập: Cài đặt = giao diện + chức năng / Chỉnh sửa = dữ liệu — giao diện quản lý dữ liệu như tải lên, phiên bản, dịch thuật được tách sang /changelog/edit
  • •Chiến lược lưu MERGE — handler save_settings hợp nhất với cài đặt hiện có. Dữ liệu của các tab khác không bị xóa dù các tab được tách riêng
  • •JS saveSettings() — chỉ gửi các trường có trong DOM. An toàn khi một số trường không được hiển thị trong môi trường tab tách rời
  • •Vị trí thẻ layout/skin — chuyển về tab Thông tin cơ bản (theo phản hồi người dùng). Tab Skin chỉ phụ trách biến của skin.json
  • •Xóa trùng lặp chiều rộng trang — xóa trường page_width khỏi tab Thông tin cơ bản (gộp vào content_width của skin)
  • •Làm phẳng sub-tab thứ cấp trong service/order — general/domain/hosting/addons trong config/service-settings-tabs.php được chuyển sang settings_tabs và nâng lên thành tab cấp cao nhất

Changed

  • •/{slug}/settings và /{slug}/edit giờ nhận diện config/system-pages.php — trước đây chỉ truy vấn BD rzx_page_contents nên trang hệ thống trả về 404. Giờ truy vấn theo thứ tự: BD → config
  • •Trường edit_view mới — chỉ định trực tiếp đường dẫn file giao diện chỉnh sửa cho trang hệ thống. Khi nhấp vào /{slug}/edit, giao diện đó được include trực tiếp (xóa bước redirect qua admin)
  • •Fallback pages-settings.php — trang hệ thống không có bản ghi trong BD giờ xây dựng $pageData từ config, ngăn chuyển hướng đến danh sách quản lý trang
  • •URL biểu tượng admin được thống nhất — /{slug}/settings và /{slug}/edit sử dụng URL chuẩn front-end

Fixed

  • •menus-api.php: sửa lỗi thiếu kiểm tra trùng lặp trước INSERT cho loại trang external — ngăn hàng trùng trong rzx_page_contents khi lưu menu hai lần
  • •Sửa lỗi bỏ sót dọn dẹp page_contents kiểu external + widget khi xóa menu — ngăn bản ghi mồ côi

Fixed

  • •Nền tiêu đề (title_bg_type, title_bg_image, title_bg_video, title_bg_overlay, title_text_color), show_title, show_breadcrumb, custom_css, custom_header_html, custom_footer_html — tất cả biến skin trang chuẩn giờ phản ánh vào giao diện công khai
  • •Partial _page-title-bg.php giờ chấp nhận biến $_contentWidth — vùng tiêu đề theo chiều rộng nội dung
  • •Biểu tượng admin được tách khỏi tiêu đề — đặt độc lập ở góc trên bên phải vùng nội dung; luôn hiển thị kể cả khi show_title=0
  • •Thêm khoảng cách trên 20px phía trên vùng tiêu đề (cân bằng bố cục nền)

Added

  • •Khóa dịch site.pages.contact được thêm cho 13 locale (ko/en/ja/zh_CN/zh_TW/de/es/fr/id/mn/ru/tr/vi) — giải quyết thiếu sót trước đây
  • •Tài liệu hướng dẫn hệ thống quản lý trang docs/PAGE_ADMIN_GUIDE.md mới — ghi lại cấu trúc tab, schema, định tuyến, quyền và phương pháp mở rộng
v2.2.2 2026-04-19 · 6 tháng trước
Cải tiến widget thống kê + Sửa tiêu đề quản trị

Added

  • •Trường số, hậu tố, nhãn (đa ngôn ngữ), biểu tượng và màu sắc cho từng mục
  • •Admin widget builder hỗ trợ thêm/sửa/xóa mục (UI chỉnh sửa kiểu stat_items mới)
  • •16 loại biểu tượng (users, chart, star, heart, check-circle, clock, calendar, globe, shield, lightning, trophy, cart, dollar, building, chat) + 10 tùy chọn màu
  • •Hoạt ảnh đếm số khi vào viewport — IntersectionObserver + easeOutCubic 1.4s
  • •Chỉ đếm các giá trị số (chuỗi như 24/7 hiển thị nguyên vẹn), giữ nguyên định dạng dấu phẩy và số thập phân
  • •widget.json v1.1.0 → v1.2.0

Fixed

  • •Sửa lỗi admin_name được lưu với tiền tố enc: và hiển thị mà không giải mã
  • •Sửa lỗi truy vấn avatar thực hiện LEFT JOIN sai vào bảng staff không tồn tại — nay truy vấn trực tiếp rzx_users.profile_image theo cấu trúc tích hợp admin_id = users.id
  • •Tự động thêm tiền tố baseUrl vào avatar có đường dẫn tương đối
v2.2.1 2026-04-19 · 6 tháng trước
Chụp URL (ảnh thu nhỏ / ảnh chụp màn hình)

Added

  • •Nút [Lấy ảnh thu nhỏ] [Lấy ảnh chụp màn hình] được tự động chèn vào bên cạnh mọi trường <input type="url"> (bao gồm biến mở rộng kiểu url) trên tất cả các bảng
  • •Ảnh thu nhỏ: render gốc 1280×960 → đầu ra 800×600 (viewport màn hình đầu tiên)
  • •Ảnh chụp màn hình: render gốc 1280×toàn_trang → đầu ra 800×thu nhỏ (trang cuộn đầy đủ, chiều cao trang thực tế)
  • •Giao diện thanh tiến trình từng bước — Kết nối máy chủ → Tải trang → Chụp màn hình → Tạo ảnh → Lưu tệp → Chờ phản hồi
  • •Tự động đặt ảnh thu nhỏ đã chụp làm ảnh đại diện — được đánh dấu board_files.is_primary=1, được widget board-showcase ưu tiên sử dụng
  • •Route mới /board/api/url-capture?type={thumbnail|screenshot}&url=... + proxy api-url-capture.php
  • •Thêm hành động set_primary vào /board/api/files — chỉ định một trong các tệp đính kèm hiện có làm ảnh đại diện

Changed

  • •Truy vấn ảnh đính kèm ORDER BY is_primary DESC, id ASC — ảnh thu nhỏ đã chụp hiển thị trước
  • •Tham số primary_file_pos được gửi lên máy chủ khi tạo bài viết để chỉ định chỉ số file đại diện
v2.2.0 2026-04-18 · 6 tháng trước
Tách Marketplace

Changed

  • •Tách sản phẩm Marketplace: chức năng mà plugin plugins/vos-marketplace/ dùng chung đã được tách thành sản phẩm độc lập → github.com/THEVOSjp/Marketplace kho lưu trữ mới, triển khai độc lập tại market.21ces.com
  • •Plugin chỉ giữ lại "giao diện phía khách hàng (duyệt, mua, cài đặt, cấp phép)" — dữ liệu, người bán và thanh toán do máy chủ marketplace xử lý hoàn toàn
  • •Các điểm tích hợp API phía Core được cập nhật

Added

  • •Modal hiển thị sau khi chọn ngôn ngữ — cảnh báo về sự cần thiết sao lưu .env + DB + storage/uploads/, và thông báo rằng mất APP_KEY sẽ không thể giải mã
  • •Xác nhận hai bước: hộp kiểm + nút xác nhận (cấm cài đặt vô điều kiện)
  • •Thêm bản dịch đầy đủ cho tất cả 13 ngôn ngữ (backup_title/body/item_env/db/uploads/warn/check/confirm/cancel)

Added

  • •scripts/register-widgets-to-marketplace.php — đăng ký hàng loạt 28 widget dựa trên tệp vào rzx_mp_items

Changed

  • •plugins/vos-marketplace/src/CatalogClient.php — URL API mặc định đổi thành https://market.21ces.com/api/v1, cập nhật đường dẫn fetchItem(), cập nhật định dạng truy vấn checkUpdates()
  • •plugins/vos-marketplace/plugin.json — cập nhật giá trị mặc định marketplace_api_url
  • •rzxlib/Core/Modules/WidgetLoader.php — URL thumbnail nay bao gồm cache-buster ?v={mtime} (xử lý cache immutable của Cloudflare)

Fixed

  • •widgets/feature-tour/widget.json — dọn dẹp trường
  • •Làm mới thumbnail một số widget (staff, testimonials, feature-tour, shop-map, shop-ranking, stylebook)
v2.1.5 2026-04-17 · 6 tháng trước

Added

  • •contact-info (v0.1.0) — thẻ liên hệ (địa chỉ/điện thoại/email/giờ làm việc + ảnh + bản đồ nhỏ)
  • •location-map (v0.1.0) — bản đồ ngang (Google Maps + thông tin 3 cột bên dưới, điều chỉnh được chiều rộng)

Added

  • •Tái cấu trúc toàn diện trang gửi mục — 3 tab (thông tin cơ bản / phát hành / bán hàng)
  • •Giấy phép (GPL/LGPL/BSD/MIT/CC/PD/thương mại), URL kho lưu trữ, URL demo, plugin phụ thuộc, ảnh banner
  • •Lịch sử phát hành, thông tin bán hàng (toggle công khai/trả phí, giá khuyến mãi/ngày kết thúc), cải thiện UX

Added

  • •Menu Developer (ID:20) bằng 13 ngôn ngữ, bổ sung description/typing_words của Hero CTA bằng 12 ngôn ngữ

Changed

  • •Làm rõ sự phân biệt tên widget (bản đồ / thẻ liên hệ), thêm fullWidthTypes vào page.php
  • •contact-form danh mục → chỉ nhãn (xóa code, cài đặt widget có thể chỉnh sửa)

Fixed

  • •board-contents/board-showcase: file_type → mime_type
  • •boards-api: thiếu is_shown_in_list + ràng buộc JSON options
  • •contact-form POST: xóa toàn bộ bộ đệm ob
  • •Hero CTA: thoát kép \n trong typing_words/description

DB Changes

  • •rzx_mp_items: thêm license, repo_url, demo_url
  • •rzx_board_extra_vars: thêm is_shown_in_list
  • •rzx_contact_messages: bảng mới
v2.1.4 2026-04-17 · 6 tháng trước

Added

  • •Widget download-hero — trang tải xuống phần mềm (tích hợp trực tiếp với version.json, 4 ngôn ngữ tích hợp sẵn, tính năng chính / yêu cầu hệ thống / lịch sử phiên bản)
  • •Trang /downloads — trang hệ thống kiểu widget, bản dịch menu 13 ngôn ngữ, is_system=1
  • •Widget contact-form (v0.1.0) — widget biểu mẫu liên hệ riêng tư 1:1 (khách có thể dùng, chọn danh mục, chống spam honeypot, gửi bằng AJAX)
  • •Widget contact-info — widget hiển thị thông tin liên hệ
  • •Widget location-map — widget bản đồ vị trí
  • •Helper dùng chung rzx_send_mail() — hàm gửi email SMTP mới trong rzxlib/Core/Helpers/mail.php
  • •Bảng rzx_contact_messages — bảng DB lưu trữ yêu cầu liên hệ
  • •Trang /contact — trang hệ thống kiểu widget, bản dịch menu 13 ngôn ngữ

Fixed

  • •Bảo vệ xóa trang hệ thống — giữ nguyên nội dung trang/widget khi xóa trang hệ thống khỏi menu (chỉ xóa mục menu)
  • •menus-api.php: kiểm tra kép qua DB is_system + slug config/system-pages.php
  • •menus-js.php: hiển thị thông báo "Chỉ xóa khỏi menu" khi xóa trang hệ thống
  • •Menu trang hệ thống đa ngôn ngữ — khi thêm trang hệ thống vào menu, nhãn 13 ngôn ngữ được tự động đăng ký từ khóa dịch site.pages.*
  • •Bản dịch trang tải xuống — thêm bản dịch site.pages.downloads cho 13 ngôn ngữ

Changed

  • •Hero trang chủ — nút Download → tải trực tiếp tại /download/voscms-latest.zip, cập nhật phiên bản v2.1.1
  • •Auth.php — gọi helper dùng chung rzx_send_mail() trước, sau đó fallback sang sendSmtpMail
  • •index.php — thêm tự động tải helper mail.php
v2.1.3 2026-04-17 · 6 tháng trước

Changed

  • •Tab Hosting — thẻ tóm tắt + thanh tiến trình sử dụng + bảng thông tin kết nối FTP/DB (hiển thị tự động khi admin cấu hình)
  • •Tab Domain — thẻ tên miền + cài đặt chính + bảng thông tin nameserver (hiển thị tự động khi admin cấu hình)
  • •Tab Mail — thông tin máy chủ mail (IMAP/SMTP) + thẻ theo tài khoản + thay đổi mật khẩu trực tiếp
  • •Tab Bảo trì — thẻ thông tin + ngày lên lịch + lịch sử công việc (hiển thị tự động khi admin ghi lại)
  • •Tab Dịch vụ bổ sung — thống nhất bố cục thẻ
  • •Thống nhất cấu trúc thông tin giống partial của admin (admin nhập vào metadata → tự động hiển thị trong trang cá nhân)

Changed

  • •Thu nhỏ khu vực nhật ký hoạt động từ tỷ lệ 1/3 xuống 1/5
  • •Bỏ hardcode giá trị NS mặc định trong tab domain của admin (chuẩn bị tích hợp API Cloudflare)

Changed

  • •Luồng cung cấp dịch vụ được cải tổ toàn diện: tên miền phụ trước → kết nối tên miền đã mua sau
  • •Quy tắc ID cung cấp: tên miền phụ hoặc SLD của tên miền đã mua
  • •Tận dụng Cloudflare wildcard tunnel (không cần thêm bản ghi A cho tên miền phụ)
  • •Thay đổi cấu hình ổ đĩa Server 2: NVMe 256 GB + SSD 2 TB + HDD 8 TB ba ổ đĩa
v2.1.2 2026-04-16 · 6 tháng trước

Added

  • •Hệ thống phân loại dịch vụ — thêm cột service_class (recurring/one_time/free), completed_at ngày hoàn thành cho dịch vụ một lần
  • •Chi tiết dịch vụ trên trang Của tôi — /mypage/services/{order} quản lý tab theo loại (hosting/tên miền/mail/bảo trì/dịch vụ bổ sung)
  • •API quản lý dịch vụ — api/service-manage.php (bật/tắt gia hạn tự động, yêu cầu gia hạn, cài đặt tên miền chính, đổi mật khẩu mail)
  • •Quản lý đơn hàng admin — /admin/service-orders danh sách đơn hàng + trang chi tiết, modal trạng thái một lần (đã tiếp nhận/đang xử lý/tạm giữ/đã hủy/hoàn thành)
  • •Menu admin — thêm menu "Đơn hàng dịch vụ" vào thanh bên (position: 65)

Added

  • •phone-display — thành phần hiển thị số điện thoại (helper format_phone() phía server), không phụ thuộc JS
  • •format_phone() — hàm PHP định dạng số điện thoại quốc tế (Hàn Quốc/Nhật Bản/Mỹ/Trung Quốc/Anh/Pháp/Đức/Úc v.v.)
  • •Cài đặt tên miền miễn phí — quản lý danh sách tên miền phụ miễn phí trong cài đặt admin (service_free_domains), hỗ trợ chọn nhiều tên miền

Fixed

  • •Thiếu đăng ký dịch vụ miễn phí — đơn hàng miễn phí không tạo bản ghi đăng ký cho tên miền/bổ sung/bảo trì v.v. → tái cấu trúc để tạo tất cả dịch vụ cùng lúc
  • •Đồng ý điều khoản trong phần thanh toán — hộp kiểm điều khoản bị ẩn cùng với phần thanh toán khi đặt hàng miễn phí → tách ra ngoài phần
  • •Xác định isFree của updateSubmitButton — btn.closest('form') NULL → sửa bằng document.querySelector
  • •Chỉ báo hoạt động thanh bên admin — $adminPath không xác định khiến tất cả menu không hoạt động → thêm khai báo biến
  • •Avatar trang Của tôi — thiếu use Auth + $user = Auth::user() trong services.php/service-detail.php
  • •Kiểm tra một lần cho dịch vụ bổ sung — cờ one_time trong cài đặt admin giờ được phản ánh đúng vào service_class khi đặt hàng
  • •Trạng thái ban đầu của dịch vụ một lần — đổi sang tạo với trạng thái pending (đã tiếp nhận) thay vì active

Changed

  • •Tái cấu trúc API đặt hàng — mã tạo đăng ký từ 3 đường thanh toán (miễn phí/thẻ/chuyển khoản) được hợp nhất vào hàm dùng chung $subscriptionData + _insertSubscriptions()
  • •UI danh sách dịch vụ — mở rộng inline → liên kết thẻ + trang chi tiết riêng
  • •Hiển thị số điện thoại — áp dụng format_phone() cho hồ sơ/danh sách thành viên/danh sách nhân viên
  • •Động hóa tên miền miễn phí — .21ces.net hardcode → tham chiếu giá trị cài đặt admin
v2.1.1-hotfix 2026-04-16 · 6 tháng trước

Fixed

  • •Lỗi 404 menu chân trang — thiếu dữ liệu trang pháp lý (terms, privacy, refund-policy, data-policy, tokushoho, funds-settlement) trong bảng rzx_page_contents → khôi phục từ DB thử nghiệm
  • •Lỗi tải ảnh/video trên widget builder — sửa lỗi FormData POST từ wrapper front-end (page-widget-builder.php) không được truyền đến AJAX handler (thêm điều kiện tải file + xử lý ob_end_clean/exit)
  • •Quyền thư mục upload — đổi chủ sở hữu storage/uploads/widgets/ thành www-data để cấp quyền ghi cho PHP-FPM

Added

  • •Menu đặt hàng dịch vụ đa ngôn ngữ — thêm bản dịch menu_item.19.title cho 13 ngôn ngữ vào bảng rzx_translations
  • •Widget Hero CTA đa ngôn ngữ — áp dụng bản dịch 13 ngôn ngữ cho tiêu đề, phụ đề và văn bản nút của banner hero trang Dev
  • •Xem trước trạng thái tải lên — thêm phản hồi trực quan khi tải ảnh/video: đang xử lý (spinner), thành công (dấu kiểm), thất bại (thông báo lỗi)
v2.1.1 2026-04-12 · 6 tháng trước

Added

  • •Màn hình chọn ngôn ngữ Bước 0 — chọn trong số 13 ngôn ngữ trước khi cài đặt bắt đầu; toàn bộ giao diện hiển thị bằng ngôn ngữ đã chọn từ đó trở đi
  • •Tách tệp dịch cài đặt — resources/lang/install.php (13 ngôn ngữ × 45 chuỗi)
  • •Cấp độ thành viên đa ngôn ngữ — Normal/Silver/Gold/VIP được tạo tự động cho 13 ngôn ngữ

Added

  • •config/admin-menu.php — menu quản trị cốt lõi được tách vào tệp cấu hình (được bảo toàn khi cập nhật Core)
  • •admin-sidebar.php được tái cấu trúc — 731 dòng hardcoded → ~200 dòng renderer động (dựa trên config + plugin.json)
  • •vos-shop plugin.json — menu hardcoded được chuyển sang định dạng menus.admin

Added

  • •Menu trượt vào — di động: thanh chuyển đổi avatar+tên → lớp phủ trượt vào bên trái (300ms ease-out)
  • •Nền mờ dần — đóng bằng cách nhấp vào nền hoặc nút X; cuộn body bị khóa

Added

  • •force_locale — áp dụng cưỡng bức ngôn ngữ mặc định (tham số ?lang=xx cho phép người dùng thay đổi)
  • •default_language — khóa cấu hình install.php ↔ Translator được thống nhất
  • •Tham số URL — ?lang=xx được phát hiện trước, lưu vào session/cookie

Fixed

  • •Skin FAQ không được áp dụng — SQL di chuyển chạy một INSERT đơn thuần cho bảng mặc định trước install.php, khiến INSERT IGNORE bị bỏ qua im lặng; đã sửa
  • •source_locale thiếu trong bảng translations — cột bị thiếu trong di chuyển cốt lõi → db_trans() thất bại hoàn toàn → thông tin người dùng/menu/i18n không hiển thị; đã sửa
  • •Chỉ báo hoạt động thanh bên tab cài đặt — thuộc tính route_prefix được thêm để menu cài đặt luôn hoạt động trên tất cả các sub-route của cài đặt
  • •Lỗi phiên tồn dư trong cài đặt — khi cài đặt mới không có .env, phiên PHP cũ làm Bước 0 bị bỏ qua; đã sửa
  • •nginx 403 — xung đột giữa thư mục vật lý admin/ và route đã được sửa (xóa try_files $uri/)
  • •Phiên bản hardcoded trong script làm rối mã — obfuscate.php giờ đọc phiên bản động từ version.json

Changed

  • •Giao diện đa ngôn ngữ widget grid/board-contents — thêm tìm kiếm rzx_translations (locale hiện tại → dự phòng tiếng Anh)
  • •Danh mục ngành của trang web — mở rộng từ 15 lên 26 (thêm: doanh nghiệp, trung tâm mua sắm, pháp lý, kế toán, CNTT, truyền thông, v.v.; 13 ngôn ngữ)
  • •Cài đặt widget grid — render.php của grid-section chuyển sang loại ô native (board-list); tiêu đề 13 ngôn ngữ
  • •Chọn ngôn ngữ Bước 4 — mở rộng từ 5 lên 13 ngôn ngữ; điền trước bằng ngôn ngữ cài đặt
  • •Chọn múi giờ — mở rộng lên 12 múi giờ bao phủ vùng người dùng 13 ngôn ngữ
v1.26.0 2026-04-01 · 7 tháng trước

Added

  • •Dịch vụ gói (bộ) hiển thị 3 cột ở trên cùng màn hình chọn dịch vụ — chủ đề màu hổ phách để phân biệt trực quan với các dịch vụ đơn lẻ
  • •Huy hiệu SET, nhãn giảm giá sự kiện, tên dịch vụ bao gồm, giá gói, gạch ngang giá gốc, hiển thị tỷ lệ giảm giá
  • •Chọn gói tự động chọn tất cả dịch vụ bao gồm (giá tính theo giá gói)
  • •Dịch vụ trong gói không thể bật/tắt riêng lẻ (ngăn tính giá sai)
  • •Chế độ chỉ định: bảng rzx_staff_bundles để lọc gói theo từng nhân viên
  • •Tham số bundles được truyền sang trang xác nhận
  • •Hỗ trợ đa ngôn ngữ: các khóa dịch kiosk liên quan đến gói được thêm cho 13 ngôn ngữ

Added

  • •Nút chuyển đổi chế độ xem — toggle [Tháng] [Tuần] [Ngày] trên thanh trên cùng (trạng thái hoạt động: xanh dương)
  • •Chế độ xem tuần — trục dọc bên trái = ngày trong tuần, trục ngang trên cùng = trục thời gian
  • •Cuộn ngang, khối đặt chỗ hiển thị dạng thanh thời gian
  • •Thuật toán làn: phát hiện chồng lấp thời gian và tự động sắp xếp xuống dưới, chiều cao hàng thay đổi
  • •Thanh bên trái ↔ cuộn dọc lưới được đồng bộ
  • •Chế độ xem ngày — ngang = trục thời gian, dọc = làn (cùng phương pháp với chế độ xem tuần)
  • •Phạm vi thời gian dựa trên giờ làm việc — dựa trên cài đặt business_hour_start/business_hour_end; tự động mở rộng cho các đặt chỗ ngoài phạm vi
  • •Truyền thời gian khi nhấp vào ô trống — trong chế độ xem tuần/ngày: tọa độ X nhấp chuột → tính thời gian đơn vị 15 phút → tự động điền thời gian bắt đầu trong modal đặt chỗ
  • •Thanh điều hướng trên cùng cố định — áp dụng overflow-x-hidden + sticky; giữ nguyên trong vùng nhìn khi cuộn ngang

Added

  • •Quản trị > Cài đặt > Chung — giao diện cài đặt giờ bắt đầu/kết thúc kinh doanh được thêm
  • •Khóa cài đặt DB business_hour_start, business_hour_end
  • •Áp dụng cho phạm vi thời gian mặc định trong chế độ xem tuần/ngày của lịch

Fixed

  • •Các trường thiếu trong POS add-service — thêm truyền start_time, end_time, staff_id, designation_fee, notes (trước đây: thời gian phía máy chủ bị hardcode, thiếu nhân viên/ghi chú)
  • •Ngăn end_time vượt qua nửa đêm — áp dụng giới hạn % 24 → min(23:59) trong ReservationHelper, API start-service và calcEnd() của form đặt chỗ
  • •Xử lý vượt nửa đêm trong xác định đang sử dụng POS — CustomerBasedAdapter xử lý end_time < start_time là vượt nửa đêm
  • •Xác thực gói đặt chỗ — sửa để cho phép tạo đặt chỗ khi chỉ chọn gói (không có dịch vụ đơn lẻ)

Changed

  • •Thay đổi tên tab: Tiếp nhận / Danh sách tiếp nhận / Đặt chỗ
  • •Danh sách tiếp nhận: nguồn walk_in, pos, kiosk, admin — hiển thị tất cả trạng thái
  • •Đặt chỗ: nguồn phone, online — hiển thị tất cả trạng thái
  • •Thứ tự sắp xếp: Chờ → Đã xác nhận → Đang sử dụng → Hoàn thành → Vắng mặt → Đã hủy; trong cùng trạng thái sắp xếp theo thời gian
  • •Hàng hoàn thành/đã hủy/vắng mặt: hiển thị với opacity-50, huy hiệu chưa phân công hiển thị

Changed

  • •Huy hiệu hoàn thành: đổi từ xám → xanh lá
  • •Huy hiệu đã hủy/vắng mặt được thêm (ẩn khi số lượng bằng 0)

Added

  • •Phần dưới thẻ: thêm nút vắng mặt cho thẻ trạng thái chờ (biểu tượng cấm), nút hủy đổi màu đỏ
  • •Modal chi tiết: nút hành động vắng mặt hiển thị cho cả trạng thái pending và confirmed
  • •Vắng mặt hàng loạt nhóm: thêm hàm POS.noShowAllServices()

Fixed

  • •Điều hướng quay lại chi tiết đặt chỗ — <a href="/reservations"> → history.back(), quay lại trang trước
  • •Đa ngôn ngữ: các khóa liên quan đến chuyển đổi chế độ xem lịch (tháng/tuần/ngày), gói, giờ làm việc được thêm cho 13 ngôn ngữ
v1.25.0 2026-04-01 · 7 tháng trước

Architecture

  • •POS được tách ra thành cấu trúc plugin độc lập
  • •resources/views/admin/reservations/pos-*.php → chuyển sang thư mục resources/views/admin/pos/
  • •Tính năng POS được bật/tắt tự động dựa trên sự tồn tại của thư mục pos/ (kiểm tra is_dir())
  • •Menu thanh bên: menu POS tự động ẩn khi không có thư mục pos/
  • •Định tuyến index.php: các route POS bị tắt khi không có thư mục pos/
  • •pos/_init.php → ủy quyền cho _init.php chung của đặt lịch (dùng chung DB, xác thực, i18n)
  • •Các endpoint API vẫn nằm trong reservations/_api.php (đảm bảo tương thích ngược)

Added

  • •Modal thanh toán thống nhất — sử dụng đồng thời điểm + tiền mặt + thẻ (thanh toán kết hợp)
  • •Điểm: tra cứu số dư, nhập thủ công hoặc dùng toàn bộ
  • •Tiền mặt: nhập số tiền
  • •Thẻ: nhập số tiền + nút tự động điền "dùng toàn bộ số dư còn lại"
  • •Trả góp: trả một lần / chọn 2–12 tháng
  • •Tự động tính tổng, tiền thừa và số tiền thiếu theo thời gian thực
  • •Với thanh toán thẻ Stripe, tiền mặt/điểm chỉ được xử lý sau khi thanh toán thẻ thành công (an toàn khi hủy)
  • •Modal chi tiết dịch vụ — hiển thị điểm
  • •Số dư điểm của thành viên luôn hiển thị ở vùng tiêu đề (hiển thị cả khi số dư bằng 0)
  • •Modal chi tiết dịch vụ — cải thiện huy hiệu nhân viên
  • •Huy hiệu đã phân công/chỉ định hiển thị trước tên nhân viên (trước đây: bên dưới tên)
  • •Di chuyển nút biên lai/in
  • •Chuyển lên trên phần thông tin chi tiết khách hàng, biên lai (trái) + in (phải)
  • •Cải thiện chức năng in
  • •In nội dung modal chi tiết dịch vụ hiện tại thay vì mở trang ngoài

Changed

  • •Bố cục thẻ — dựa trên grid → thẻ kích thước cố định với flex-wrap
  • •Kích thước thẻ cố định: mặc định 320×240px (small: 260×200, large: 380×280)
  • •Kích thước thẻ không thay đổi theo chiều rộng màn hình; tự động xuống dòng
  • •Modal thanh toán thẻ — mở rộng lên rộng 1030px, cao 800px

Fixed

  • •Lỗi cross-origin API đã được giải quyết
  • •$baseUrl bị cố định thành APP_URL trong .env, gây lỗi fetch từ host/HTTPS khác
  • •Bảng điều khiển: URL fetch đổi thành đường dẫn tương đối (/update-api.php)
  • •_init.php đặt lịch: $baseUrl đổi thành chuỗi rỗng để tất cả fetch dùng đường dẫn tương đối
  • •Hoàn toàn giải quyết vấn đề mixed-content trong môi trường proxy HTTPS Cloudflare
  • •Lỗi thực thi migration DB — "Failed to fetch" đã giải quyết (vấn đề cross-origin)
  • •Lỗi xử lý tiền mặt trước khi hủy thanh toán kết hợp Stripe
  • •Trước: tiền mặt được xử lý trước → khi hủy thanh toán thẻ, tiền mặt đã được áp dụng
  • •Sau: tiền mặt/điểm chỉ được xử lý sau khi thanh toán thẻ Stripe thành công

i18n

  • •pos_pay_after_points — số tiền sau khi áp dụng điểm
  • •pos_pay_proceed — tiến hành thanh toán
  • •pos_pay_remainder — dùng toàn bộ số dư còn lại
  • •pos_pay_installment — trả góp
  • •pos_pay_lump_sum — trả một lần
  • •pos_pay_months — tháng
  • •pos_pay_total_pay — tổng cộng
  • •pos_pay_short — thiếu
  • •show_receipt — biên lai
  • •show_print — in
v1.18.0 2026-03-29 · 7 tháng trước

Added

  • •Hàm định dạng ngày đa ngôn ngữ — formatReservationDate($dateString, $locale)
  • •Hỗ trợ 13 ngôn ngữ (ko, en, ja, zh_CN, zh_TW, de, es, fr, id, mn, ru, tr, vi)
  • •Tự động bản địa hóa ngày và thứ trong tuần trên trang chi tiết đặt chỗ
  • •Dự phòng: locale không được hỗ trợ → định dạng tiếng Anh

Changed

  • •Xử lý đa ngôn ngữ trang chi tiết đặt chỗ
  • •Tên dịch vụ, tên nhân viên và tên gói đã được bản địa hóa (dựa trên bảng translations trong DB)
  • •Tích hợp hàm định dạng ngày
  • •Nhãn trạng thái thanh toán được bản địa hóa (trường payment_status)
  • •Hỗ trợ đa ngôn ngữ trạng thái thanh toán
  • •Thêm mục payment vào tất cả file ngôn ngữ (11 ngôn ngữ)
  • •Bản dịch cho: chưa thanh toán, đã thanh toán, thanh toán một phần, đã hoàn tiền

Fixed

  • •Trang chi tiết đặt chỗ: tên nhân viên và tên dịch vụ trước đây không được bản địa hóa nay hiển thị chính xác
  • •Nhãn trạng thái thanh toán: khắc phục lỗi chỉ hiển thị bằng tiếng Hàn
  • •Thống nhất xử lý đa ngôn ngữ dựa trên hàm _tr()

Layout & UI

  • •Thống nhất chiều rộng trang (max-w-5xl → max-w-7xl)
  • •Trang bảng (danh sách, đọc, viết): max-w-5xl → max-w-7xl
  • •Trang ngoài (page.php): cập nhật giá trị mặc định và giá trị cài đặt DB
  • •Chi tiết đặt chỗ / tra cứu đặt chỗ / trang nhân viên: cập nhật giá trị cài đặt DB
  • •Kết quả: chiều rộng tất cả các trang nay đồng nhất với trang đặt chỗ

Documentation

  • •Thêm tài liệu chi tiết cho formatReservationDate() trong COMPONENT_MANUAL.md
  • •Ngôn ngữ được hỗ trợ và bảng định dạng
  • •Ví dụ sử dụng và cấu trúc nội bộ
  • •Lưu ý và các hàm liên quan
v1.16.0 2026-03-23 · 7 tháng trước

Added

  • •Thanh menu dưới cùng di động — Nhân viên / Đặt chỗ / Trang chủ / Đăng nhập (hoặc Của tôi) / Đăng ký / Thêm, với tô sáng trang hiện tại
  • •Bảng "Thêm" trên di động — menu chính + Trang của tôi / Đăng xuất
  • •Cài đặt bố cục/skin được áp dụng thực sự — site_layout, site_page_skin, site_board_skin, site_member_skin → phản ánh vào rendering
  • •Tham số no_layout — chỉ nội dung không có bố cục (dùng để xem trước)
  • •Thêm khóa dịch — common.nav.staff, common.nav.more (13 ngôn ngữ)

Fixed

  • •Áp dụng bố cục cho các trang thành viên (login/register/forgot/reset): xóa header trùng lặp bằng cách trích xuất <main> của skin
  • •Sửa lỗi khai báo trùng lặp ImageCropper/ProfilePhotoCropper trong skin thành viên
  • •Sửa lỗi include_once của trình tải menu: menu base-header bị thiếu khi tải trước trong closure của skin
  • •apple-mobile-web-app-capable lỗi thời → mobile-web-app-capable (8 file)
  • •Ẩn nút đăng nhập/đăng ký trên header ở mobile (thay thế bằng thanh menu dưới cùng)
  • •Hỗ trợ iOS safe-area cho thanh menu dưới cùng

Changed

  • •Gộp các trang thành viên từ bố cục riêng sang bố cục mặc định (login/register/forgot/reset)
  • •Xóa khoảng cách dưới footer (thanh menu di động dùng vị trí cố định)
v1.15.3 2026-03-22 · 7 tháng trước

Added

  • •Bảng cài đặt chi tiết layout — tải AJAX biểu mẫu cài đặt dựa trên SkinConfigRenderer
  • •Cài đặt menu layout — mục menus của layout.json → tự động tạo dropdown sitemaps từ DB
  • •Hỗ trợ tab SkinConfigRenderer — thêm thuộc tính tab vào vars sẽ tự động tạo UI dạng tab
  • •Tái cấu trúc SkinConfigRenderer — phương thức duy nhất renderVar() thống nhất, tách renderFormFlat/renderFormWithTabs, renderDependsOnJs dùng chung
  • •Mở rộng layout.json — menus (GNB/FNB), 14 vars (header/logo/màu sắc/footer/tùy chỉnh), 13 ngôn ngữ
  • •Tích hợp xem trước layout — chọn "Tắt" hiển thị xem trước với ?no_layout=1

Fixed

  • •Truy vấn menu quản lý layout: sửa tên bảng rzx_menus → rzx_sitemaps
  • •Điều chỉnh độ rộng panel trung tâm + whitespace-nowrap cho liên kết hành động

Pending

  • •Áp dụng giá trị cài đặt layout/skin vào rendering trang thực tế (phiên tiếp theo)
v1.15.2 2026-03-22 · 7 tháng trước

Added

  • •Trang quản lý bố cục — cấu trúc 3 bảng: bên trái xem trước+menu, bên phải danh sách giao diện, bảng cài đặt chi tiết
  • •Mỗi mục giao diện: ảnh thu nhỏ + liên kết hành động cài đặt chi tiết/tạo bản sao/xóa
  • •Tùy chọn "Vô hiệu hóa" / "Cài giao diện khác"
  • •Lưu theo 4 danh mục: bố cục, trang, bảng, thành viên (site_layout, site_page_skin, site_board_skin, site_member_skin)

Changed

  • •"Quản lý thiết kế" → đổi tên thành "Quản lý bố cục" (13 ngôn ngữ: admin.php + site.php)
v1.15.1 2026-03-22 · 7 tháng trước

Changed

  • •15 trang quản lý site → áp dụng header dùng chung _head.php
  • •Bảng tin: boards, boards-create, boards-edit, boards-trash
  • •Menu: menus
  • •Thiết kế: design
  • •Trang: pages, pages-settings, pages-edit-content, pages-document, pages-compliance, pages-widget-builder
  • •Widget: widgets, widgets-create, widgets-marketplace
  • •Các trang chế độ embed (boards-edit, pages-settings, pages-edit-content) chỉ áp dụng _head.php khi không ở chế độ embed
  • •Hoàn tất thống nhất header/bố cục toàn bộ trang admin
v1.15.0 2026-03-22 · 7 tháng trước

Added

  • •Mô-đun widget hệ thống — 4 widget: staff (giới thiệu nhân viên), booking (đặt chỗ), lookup (tra cứu đặt chỗ), cta001 (banner kêu gọi đặt chỗ)
  • •Trang hệ thống — staff, booking, lookup được đăng ký vào DB (is_system=1) + định tuyến (/staff, /booking, /lookup)
  • •Render trang dựa trên widget — các trang staff/booking/lookup render widget khi có widget được đặt, quay về render cũ khi không có
  • •Tự động đăng ký widget vào DB — gọi syncToDatabase() tự động đăng ký widget khi thêm thư mục widget
  • •Danh mục widget system — dịch sang 13 ngôn ngữ (widgets.categories + widget_builder.cat)
  • •Thống nhất danh sách trang — render vòng lặp trang hệ thống + bộ icon bánh răng/chỉnh sửa/xem trước thống nhất
  • •Thống nhất tiêu đề trang quản trị — $pageSubTitle + $pageSubDesc (xuất chung qua _head.php)
  • •Khóa dịch được thêm — staff.admins, staff.attendance.report/stats, points.description, v.v.

Fixed

  • •page_slug = 'home' cố định trong widget builder → xử lý động qua $_GET['slug']
  • •AJAX save/preview widget builder với home cố định → $pageSlug động
  • •URL xem trước widget builder → $pageSlug động (trang chủ cố định → từng trang)
  • •Thiếu require WidgetLoader trong widget preview_widget — đã sửa
  • •Đường dẫn ảnh trong view thẻ dịch vụ (tiền tố /storage/)
  • •Chiều rộng cài đặt kiosk max-w-3xl → 100% thống nhất
  • •Tiêu đề POS "Quản lý Đặt chỗ" → đổi tên thành "POS"

Changed

  • •10 trang quản lý nhân viên + 4 trang quản lý thành viên → áp dụng tiêu đề chung _head.php
  • •Trang kiosk/bundle đã áp dụng _head.php
  • •Cài đặt ngôn ngữ kiosk grid → flex-wrap đáp ứng
  • •Danh sách trang: trang hệ thống được render qua vòng lặp dựa trên dữ liệu
v1.14.1 2026-03-22 · 7 tháng trước

Added

  • •Tab skin trang — thông tin cơ bản của skin + cài đặt biến mở rộng (dựa trên SkinConfigRenderer)
  • •Skin áp dụng cho tất cả loại trang — cài đặt skin áp dụng cho document/widget/external như nhau
  • •Hệ thống nền tiêu đề — nền hình ảnh/video + lớp phủ + màu chữ (partial dùng chung _page-title-bg.php)
  • •Hệ thống depends_on — khai báo phụ thuộc giữa các trường trong skin.json, renderer tự động tạo JS (hỗ trợ checkbox/radio)
  • •Tải lên file skin — tải lên hình ảnh/video qua multipart (storage/skins/page/{skin}/)
  • •Bộ chọn bố cục/skin kiểu thẻ — chuyển sang UI thẻ thumbnail trong tab thông tin mô-đun
  • •Hệ thống SEO — helper SEO, mẫu tiêu đề, meta tag OG/Twitter, trích xuất nội dung
  • •Tải lên OG Image — nhập URL + tải file + xem trước
  • •Modal kết quả dùng chung — UI modal lưu thành công/thất bại thống nhất (hỗ trợ 13 ngôn ngữ)
  • •Giao diện thẻ dịch vụ — thẻ nền hình ảnh toàn màn hình + nút chuyển đổi bảng/thẻ
  • •Sắp xếp dịch vụ kéo-thả — thay đổi thứ tự + lưu DB ở cả hai chế độ xem
  • •Phân công/chỉ định nhân viên đặt chỗ — 2 nút (phân công/chỉ định) trong chi tiết đặt chỗ
  • •UI nguồn đặt chỗ — chọn đặt chỗ qua điện thoại / trực tiếp / trực tuyến
  • •Cài đặt đặt chỗ qua điện thoại — toggle bật/tắt trong cài đặt cơ bản của dịch vụ
  • •Header bảo mật — X-Frame-Options + CSP frame-ancestors
  • •PAGE_SYSTEM.md — tài liệu phát triển hệ thống trang
  • •PRD_OrderSystem.md — tài liệu lập kế hoạch hệ thống đặt món tại bàn
  • •PRD_KioskSystem.md — tài liệu lập kế hoạch hệ thống kiosk

Fixed

  • •Cài đặt favicon từ DB đã áp dụng (front / admin / skin layout — 4 nơi)
  • •URL migration dashboard window.location.origin → $baseUrl (môi trường thư mục con)
  • •URL API chế độ embed cài đặt trang → đường dẫn admin được chỉ định trực tiếp
  • •Modal kết quả i18n: dùng thông báo locale khi render trang thay vì phản hồi API
  • •Fallback giá trị skin trống trong tab skin ("" → default)
  • •Vấn đề tiêu thụ kép php://input trong pages-settings.php đã giải quyết

Changed

  • •Kiosk / cài đặt kiosk / trang bundle → áp dụng header dùng chung _head.php
  • •Lưu cài đặt skin JSON → chuyển FormData (multipart) (hỗ trợ tải file)
  • •Thêm tham số $baseUrl vào SkinConfigRenderer (xem trước hình ảnh/video)
  • •Bản dịch skin 13 ngôn ngữ (skin.json + site.php + common.php)
v1.13.0 2026-03-21 · 7 tháng trước

Added

  • •Hệ thống trang hoàn chỉnh — tự động tạo trang khi tạo trang tài liệu/widget/ngoài từ menu
  • •Trình kết xuất trang động — page.php (tài liệu→HTML, widget→WidgetRenderer, ngoài→iframe/include)
  • •Cài đặt môi trường trang — 3 tab (cơ bản / bố cục & skin / SEO), lưu dạng JSON page_config_{slug}
  • •Chỉnh sửa nội dung trang — chỉnh sửa tiêu đề & nội dung theo ngôn ngữ, đổi slug, đổi loại, xóa
  • •Danh sách quản lý trang động — tự động tải trang người dùng từ DB, biểu tượng & huy hiệu theo loại
  • •Biểu tượng quản trị phía trước — bánh răng (cài đặt) + chỉnh sửa (nội dung) hiển thị riêng biệt
  • •iframe trang ngoài — hướng dẫn "mở trong cửa sổ mới" hiển thị khi tải thất bại
  • •File PHP/HTML nội bộ — render bên trong bố cục RezlyX qua include

Fixed

  • •URL lối tắt menu #menu_{id} → lưu URL menu thực tế
  • •Chỉnh sửa menu hiển thị cùng cấu trúc UI lối tắt như lúc tạo
  • •Lưu menu phản ánh URL lối tắt (formMenuType → cơ sở hiển thị panel)
  • •Thêm bản dịch menu cho 13 ngôn ngữ (12 mục menu × 13 ngôn ngữ)
  • •Sửa đường dẫn khóa dịch của trình soạn thảo tài liệu trang (admin.site.pages. → site.pages.)

Changed

  • •Thêm cột page_type vào DB rzx_page_contents (document/widget/external)
  • •Xóa menu nay sẽ đồng thời xóa trang liên kết + dữ liệu bản dịch
v1.12.5 2026-03-21 · 7 tháng trước

Fixed

  • •Sửa URL lối tắt menu — giờ lưu URL menu thực thay vì #menu_{id}
v1.12.4 2026-03-21 · 7 tháng trước

Fixed

  • •Loại danh sách cài đặt skin không được áp dụng — sửa lỗi localStorage cache ghi đè lên cài đặt skin
  • •Khi không cho phép chuyển đổi kiểu, chỉ dùng cài đặt skin; khi cho phép, localStorage được ưu tiên
  • •Loại bỏ việc gửi trùng lặp trường ẩn của checkbox (trạng thái chưa chọn nay được xử lý trong JS)
v1.12.3 2026-03-20 · 7 tháng trước

Fixed

  • •Sửa lỗi thiếu khóa dịch bảng tin cho tiếng Anh/Nhật (source_locale, reply, style, board_settings, v.v.)
  • •Áp dụng fallback đa ngôn ngữ cho tên danh mục (locale → en → gốc)
  • •Hỗ trợ đa ngôn ngữ cho nội dung danh sách bảng tin (xem trước webzine/thẻ/thư viện ảnh)
v1.12.2 2026-03-20 · 7 tháng trước

Fixed

  • •Dự phòng đa ngôn ngữ nội dung danh sách bảng — nội dung được dịch áp dụng cho xem trước webzine/thẻ/thư viện (ngôn ngữ → en → gốc)
  • •Thiếu file skin trên môi trường production — tạo thư mục skins/default/board/ qua FTP và tải lên skin.json/ảnh thu nhỏ
v1.12.1 2026-03-20 · 7 tháng trước

Fixed

  • •Cài đặt skin không hiển thị trên môi trường production — đồng bộ toàn bộ tệp được tổ chức lại
  • •Cấu trúc tệp CLAUDE.md + BOARD_SYSTEM.md được cập nhật toàn diện
v1.12.0 2026-03-20 · 7 tháng trước

Added

  • •Hệ thống cài đặt skin hoàn chỉnh — tạo form động dựa trên skin.json + áp dụng cho các bảng thực tế
  • •Nhóm các phần (cơ bản / danh sách / liên kết / thiết kế / nền tiêu đề / tùy chỉnh)
  • •Thêm kiểu nhập radio và video
  • •Tải lên file ảnh/video (FormData multipart)
  • •Tính năng xóa ảnh/video
  • •Bảng thông tin skin (tác giả / URL / email / ngày / phiên bản / hình thu nhỏ)
  • •Hình ảnh/video nền tiêu đề — cài đặt kiểu nền, chiều cao, độ mờ overlay và màu chữ
  • •4 kiểu bố cục danh sách — danh sách / webzine / gallery / thẻ; tách file skin + hỗ trợ ghi đè
  • •Gallery: hình ảnh toàn khung cover + hiệu ứng trượt khi hover
  • •Webzine: hình thu nhỏ + tiêu đề + xem trước + thẻ thông tin meta
  • •Tách bài viết thông báo ra danh sách phía trên (_list-notices.php)
  • •Áp dụng cài đặt skin — primary_color, border_radius, posts_per_row, allow_style_switch, show_category, bảng liên kết, Font Awesome, CSS/HTML tùy chỉnh
  • •Tự động hợp nhất giá trị mặc định skin.json — giá trị mặc định skin.json được áp dụng dù chưa lưu vào DB

Fixed

  • •skin_config không được lưu vào DB (hành động update của boards-api.php thiếu skin_config)
  • •Lưu skin đổi từ URLSearchParams → FormData (multipart) để hỗ trợ tải lên file
  • •Hỗ trợ tự động phân tích mảng $_POST['skin_config']
v1.11.3 2026-03-20 · 7 tháng trước

Fixed

  • •Áp dụng fallback đa ngôn ngữ cho tiêu đề bài viết trước/tiếp theo trên trang chi tiết bài viết (locale → en → gốc)
v1.11.2 2026-03-20 · 7 tháng trước

Fixed

  • •Dự phòng đa ngôn ngữ tiêu đề danh sách bảng — truy vấn bản dịch trên tất cả các ngôn ngữ (đã loại bỏ giới hạn chỉ tiếng Hàn), dự phòng tiếng Anh có xem xét ngôn ngữ nguồn
v1.11.1 2026-03-20 · 7 tháng trước

Fixed

  • •Cải thiện phát hiện URL đơn lẻ cho thẻ OG — giờ đây duyệt ngược lên phần tử cha cấp khối, xử lý đúng các URL được bọc trong thẻ nội tuyến như <font> / <span>
v1.11.0 2026-03-20 · 7 tháng trước

Added

  • •Tự động liên kết URL — tự động phát hiện URL trong nội dung/trình soạn thảo bảng → chuyển đổi thành thẻ <a>
  • •Thẻ xem trước liên kết OG — thẻ định dạng banner SNS (thumbnail + tiêu đề + mô tả + tên miền) được tạo tự động
  • •Trình soạn thảo: nhập/dán URL + Enter → gọi OG API → chèn thẻ
  • •Nội dung: liên kết URL độc lập → tự động chuyển đổi thành thẻ OG
  • •Mô-đun OgFetcher — trích xuất metadata OG/Twitter Card, favicon, xử lý mã hóa tự động
  • •OG API — endpoint /board/api/og
  • •board-autolink.js — JS tích hợp tự động liên kết + thẻ OG (tải toàn cục từ base-header)
v1.10.2 2026-03-20 · 7 tháng trước

Fixed

  • •Căn chỉnh hình ảnh trong editor/nội dung — ghi đè img { display: block } của Tailwind preflight
  • •Tạo CSS dùng chung board-content.css (thống nhất hiển thị editor + nội dung)
  • •Tải toàn cục từ base-header.php (tất cả trang frontend)
  • •Thêm kiểu editor toàn cục vào multilang-modal.php (tất cả phiên bản Summernote trong admin)
  • •Xóa class prose khỏi nội dung bảng; các style inline của editor hiện được giữ nguyên 100%

Changed

  • •Ghi lại quy tắc style nội dung bảng trong CLAUDE.md (class board-content là bắt buộc)
v1.10.1 2026-03-20 · 7 tháng trước

Fixed

  • •Sửa lỗi dữ liệu danh mục cũ được tải vào modal đa ngôn ngữ khi thêm danh mục bảng (tạo langKey tạm thời duy nhất)
  • •Thêm giá trị mặc định comment_max_depth là 3 vào migration 021
v1.10.0 2026-03-20 · 7 tháng trước

Added

  • •Biến mở rộng bảng — mô-đun thành phần ExtraVarRenderer (15 loại: render input/display theo từng loại)
  • •Đa ngôn ngữ biến mở rộng — lưu trữ độc lập giá trị biến mở rộng theo từng ngôn ngữ (tích hợp rzx_translations, chuỗi dự phòng)
  • •Lưu trữ riêng biệt đa ngôn ngữ bài đăng bảng — khi chỉnh sửa bằng ngôn ngữ gốc lưu trực tiếp vào board_posts; ngôn ngữ khác lưu bản dịch vào rzx_translations
  • •Chuỗi dự phòng đọc bài đăng bảng — hiển thị tiêu đề/nội dung/biến mở rộng theo thứ tự: locale hiện tại → en → bản gốc
  • •Trả lời lồng nhau — hỗ trợ bình luận lồng nhau 3 cấp, sắp xếp cây đệ quy, biểu mẫu trả lời nội tuyến
  • •Thích/Không thích bình luận — nút thích theo từng bình luận + API
  • •Truy cập frontend cài đặt bảng — biểu tượng bánh răng admin → /board/{slug}/settings bố cục frontend
  • •Liên kết tiêu đề admin bảng — nhấp vào tiêu đề trong danh sách bảng admin chuyển đến bảng đó

Fixed

  • •Kiểm tra quyền admin API bảng: $currentUser['role'] → $_SESSION['admin_id'] (cập nhật 4 tệp)
  • •Thông báo ngôn ngữ gốc chỉ hiển thị cho tác giả/admin
  • •Liên kết tab chế độ nhúng cài đặt bảng hỗ trợ URL frontend

Changed

  • •Thêm cột JSON extra_vars vào DB rzx_board_posts
  • •Giá trị mặc định comment_max_depth thay đổi từ 0 → 3
  • •Thanh hành động bình luận được hợp nhất (biểu tượng thích/không thích/trả lời/xóa)
v1.9.4 2026-03-20 · 7 tháng trước

Added

  • •Dữ liệu bảng tin mặc định — di chuyển bảng tin thông báo, hỏi đáp, FAQ và bảng tin tự do (020_default_boards_v193.sql)
v1.9.3 2026-03-20 · 7 tháng trước

Added

  • •Đặt lại nhóm thành viên — khởi tạo với dữ liệu mặc định (7 nhóm + bản dịch 13 ngôn ngữ)
  • •Đặt lại cài đặt điểm — khôi phục giá trị cấu hình / điểm cấp độ / liên kết nhóm về mặc định (không ảnh hưởng số dư thành viên)
  • •Nhóm thành viên đa ngôn ngữ — áp dụng thành phần chung rzx_multilang_input() cho tên nhóm / mô tả quyền lợi
  • •Kéo thả nhóm thành viên — sắp xếp thẻ bằng SortableJS + tự động lưu

Fixed

  • •Hiển thị bản dịch thẻ nhóm thành viên theo ngôn ngữ (xem thẻ + modal chỉnh sửa)
  • •Sửa lỗi hỏng dữ liệu dịch đa ngôn ngữ nhóm thành viên (lưu lại UTF-8 bằng PHP)
  • •Sửa tên cột bảng cài đặt mô-đun điểm (board_name → title)
  • •Giải quyết xung đột collation trong danh sách thành viên điểm (thống nhất utf8mb4_unicode_ci)
  • •Chạy migration DB sản xuất (019_point_system_v190.sql)
v1.9.0 2026-03-20 · 7 tháng trước

Added

  • •Hệ thống quản lý điểm thưởng (tín dụng) — cấu trúc 3 tab (Cài đặt cơ bản / Cài đặt theo module / Danh sách điểm thành viên)
  • •Cấu trúc 3 trường điểm — point (điểm hoạt động), balance (tín dụng thanh toán), total_accumulated (điểm tích lũy, cơ sở tính cấp độ)
  • •Trọng số điểm tích lũy — trọng số thanh toán / trọng số hoạt động riêng biệt, khách hàng trả tiền được ưu tiên lên cấp
  • •Đổi điểm — chuyển đổi điểm → tín dụng (tỷ lệ, đơn vị, điểm tối thiểu có thể cấu hình)
  • •17 hạng mục cộng/trừ điểm — cùng cấu trúc với Rhymix (thu hồi khi xóa, giới hạn thời gian, loại trừ thông báo)
  • •Cài đặt theo module — cấu hình riêng 15 mục điểm cho từng bảng
  • •Danh sách điểm thành viên — 4 cột (điểm/tín dụng/tích lũy/cấp độ), tìm kiếm, chỉnh sửa từng người
  • •Điểm cấp độ — tính toán dựa trên công thức, điều chỉnh cấp độ tối đa động, liên kết nhóm
  • •Tài liệu hệ thống điểm — POINT_SYSTEM.md tài liệu thiết kế chi tiết
  • •Kéo thả nhóm thành viên — thay đổi thứ tự thẻ bằng SortableJS + tự động lưu
  • •Đa ngôn ngữ nhóm thành viên — áp dụng component chung rzx_multilang_input() cho tên nhóm/mô tả quyền lợi
  • •Dữ liệu seed nhóm thành viên — 7 nhóm × 13 ngôn ngữ dữ liệu dịch đa ngôn ngữ

Changed

  • •Thêm cột balance, total_accumulated vào DB rzx_member_points
  • •Thay đổi rzx_point_levels.group_id từ INT sang CHAR(36) (tương thích UUID)
  • •Thống nhất collation của rzx_point_levels, rzx_member_points sang utf8mb4_unicode_ci
  • •Cập nhật layout trang bundle (sidebar-main-content → mẫu dashboard flex-1 ml-64)
  • •Sửa đơn vị tiền tệ trang bundle $config['currency'] → $siteSettings['service_currency']
  • •Thay đổi thời lượng dịch vụ từ select → input number + datalist
  • •Ghi tài liệu quy tắc UI nhập đa ngôn ngữ vào CLAUDE.md (bắt buộc dùng rzx_multilang_input)
v1.8.3 2026-03-20 · 7 tháng trước

Added

  • •Trang quản lý chi tiết gói — chỉnh sửa thông tin cơ bản gói, tải ảnh bìa, chỉnh sửa thành phần dịch vụ, liên kết nhân viên, bật/tắt hoạt động
  • •Giảm giá sự kiện — giá sự kiện theo gói, thời hạn (bắt đầu/kết thúc), cài đặt nhãn; tự động kích hoạt trong thời hạn
  • •Thiết kế thẻ danh sách gói — bố cục thẻ lưới, tiêu đề ảnh, huy hiệu sự kiện/giảm giá, thanh hành động ghim ở dưới
  • •Ảnh nền gói đề xuất — ảnh bìa làm nền + lớp phủ gradient trên thẻ gói trong trang chi tiết nhân viên của khách hàng
  • •Nhập trực tiếp thời lượng dịch vụ — select → nhập số (5–480 phút, bước 5 phút) + danh sách đề xuất datalist

Changed

  • •DB rzx_service_bundles thêm cột: event_price, event_start, event_end, event_label
  • •API danh sách gói: thêm total_duration và các cột sự kiện
  • •Tệp dịch (ko, en, ja): thêm khóa quản lý chi tiết gói + giảm giá sự kiện
v1.8.1 2026-03-19 · 7 tháng trước

Added

  • •Trang cài đặt POS — kích thước thẻ, hiển thị ảnh/giá/điện thoại, độ mờ, tab mặc định, tự động làm mới, âm thanh cảnh báo, bắt buộc phân công nhân viên, tự động phân công
  • •Cài đặt POS được áp dụng — kích thước thẻ/ảnh/giá/điện thoại/độ mờ/tự động làm mới/tab mặc định đều được phản ánh trong POS
  • •Tự động phân công nhân viên — khi được bật trong cài đặt POS, tự động phân công nhân viên khi check-in tại kiosk (có thể thực hiện dịch vụ + ít đặt chỗ nhất trong ngày)
  • •Huy hiệu nhân viên trên thẻ POS — chỉ báo đã phân công/chưa phân công; nút tiếp tục bị vô hiệu khi chưa phân công
  • •Nền ảnh dịch vụ POS — ảnh dịch vụ đại diện làm nền trên tiêu đề + khu vực khách hàng của modal chi tiết dịch vụ
  • •Nhân viên is_visible — kiểm soát khả năng hiển thị trong danh sách; nhân viên bị ẩn được loại khỏi đặt chỗ/POS/kiosk
  • •Banner thẻ nhân viên — ảnh banner + huy hiệu trạng thái trên thẻ nhân viên của quản trị viên
  • •Tự động phân công tại kiosk — check-in với staff_id=NULL; phân công do quản trị viên thực hiện trong POS

Fixed

  • •Phân công nhân viên POS: danh sách dịch vụ cập nhật ngay sau khi phân công (ngăn cache)
  • •Sửa tham số API phân công nhân viên (reservation_id → reservation_ids[])
  • •Nhiều bảng/cột bị thiếu đã được sửa trong môi trường production (di chuyển 018 được củng cố)
  • •Thêm route đăng xuất quản trị viên
  • •Đặt route trước xác thực kiosk
v1.7.0 2026-03-18 · 7 tháng trước

Added

  • •Hệ thống bố cục cơ sở — layouts/base-header.php + base-footer.php, tự động áp dụng ob_start trong index.php, header/footer dùng chung cho mọi trang khách hàng
  • •Giao diện người dùng bảng tin — trang danh sách, chi tiết, viết/chỉnh sửa, trình soạn thảo Summernote, đính kèm tệp kéo & thả
  • •URL ngắn bảng tin — truy cập /free, /notice/3, v.v. mà không cần tiền tố /board/; tự động khớp slug trong DB
  • •Trang tra cứu đặt chỗ — URL ngắn /lookup, tìm kiếm theo số đặt chỗ / email / số điện thoại
  • •Trang chi tiết đặt chỗ — /booking/detail/{số}, bong bóng lời chào nhân viên, thông tin dịch vụ/thanh toán/hủy
  • •Trang hủy đặt chỗ — /booking/cancel/{số}, nhập lý do hủy
  • •Chi tiết đặt chỗ trong trang cá nhân — /mypage/reservations/{id}, thanh bên + thông tin chi tiết
  • •Bảng tin đa ngôn ngữ — original_locale (ngôn ngữ bản nháp đầu tiên) + source_locale (ngôn ngữ nội dung hiện tại), chuỗi dự phòng (source → en → original)
  • •Lời chào nhân viên — greeting_before (trước dịch vụ) + greeting_after (sau dịch vụ), đa ngôn ngữ, hiển thị theo trạng thái đặt chỗ
  • •Menu thả xuống hồ sơ quản trị viên — ảnh/chữ cái đầu + tên + liên kết trang chủ / trang cá nhân / đăng xuất
  • •Liên kết quản trị viên trên header khách hàng — khi đăng nhập bằng tài khoản admin, menu thả xuống hiển thị liên kết đến trang quản trị

Changed

  • •Thống nhất bố cục cho tất cả trang khách hàng (xóa cấu trúc HTML riêng lẻ, LayoutManager áp dụng tự động)
  • •Điều kiện hiển thị danh mục bảng tin đổi từ show_category sang hide_categories
  • •URL bảng tin đổi từ /board/free sang URL ngắn /free theo mặc định
  • •"Admin" trên thanh trên của quản trị viên được thay bằng tên đăng nhập thực + ảnh hồ sơ

Fixed

  • •Thiếu cột rzx_users.role → xác định quản trị viên nay dựa vào $_SESSION['admin_id']
  • •Thiếu cột rzx_users.nick_name → dùng name + giải mã Encryption
  • •rzx_staff.profile_image → sửa thành tên cột avatar
  • •Chuyển đổi kiểu int→string cho category_id trong model Service
  • •Tra cứu đặt chỗ theo email/điện thoại dùng tìm kiếm văn bản thuần (dữ liệu chưa mã hóa)
v1.6.1 2026-03-18 · 7 tháng trước

Added

  • •6 tab quản trị bảng tin — Cài đặt cơ bản, Quản lý danh mục, Biến bổ sung, Phân quyền, Cài đặt bổ sung, Skin
  • •Hợp nhất tab cài đặt cơ bản — Thông tin cơ bản + SEO + Chọn layout + Chọn skin + Hiển thị + Danh sách + Nâng cao (có thể thu/mở)
  • •Các thành phần dùng chung — 8 tệp components/board/section-*.php (basic, seo, layout-select, skin-select, display, list, advanced, js), tái sử dụng trên trang tạo/chỉnh sửa
  • •Thành phần nhập đa ngôn ngữ — hàm rzx_multilang_input(), chế độ text/editor, nút địa cầu inline
  • •Nâng cao quản lý danh mục — cấu trúc cây (parent_id), modal chỉnh sửa (tên/màu font/mô tả/nhóm được phép/mở rộng/danh mục mặc định), sắp xếp kéo thả với SortableJS, tải động cấp độ thành viên từ DB
  • •Tab biến bổ sung — bảng rzx_board_extra_vars, 15 loại nhập (bao gồm text_multilang, textarea_multilang, textarea_editor), hỗ trợ đa ngôn ngữ, sắp xếp kéo thả
  • •Tab phân quyền — Quyền truy cập (all/member/grade:*/admin_staff/admin), quản trị viên module (tìm kiếm người dùng chung, ảnh đại diện, phạm vi quyền), thông tin mail thông báo
  • •Tab cài đặt bổ sung — Bảng tin tích hợp, tài liệu (lịch sử/đề xuất/báo cáo), bình luận (số lượng/độ sâu/duyệt/đề xuất/báo cáo), trình soạn thảo WYSIWYG (ma trận quyền), tệp (nhóm tải xuống), nguồn cấp (RSS công khai/bản quyền)
  • •Hệ thống skin — định dạng skin.json, SkinConfigRenderer, hỗ trợ "multilang": true, thẻ thông tin skin
  • •Hệ thống layout — định dạng layout.json, chọn kiểu thẻ trong cài đặt cơ bản
  • •Tìm kiếm người dùng chung — thành phần user-search.php, mã hóa/giải mã, ảnh đại diện, có thể tái sử dụng ở bất kỳ đâu
  • •Quản trị viên module — bảng rzx_board_admins, quyền bài đăng/bình luận/cài đặt, đăng ký thông báo
  • •Mở rộng cài đặt nâng cao — loại trừ admin khỏi ẩn danh, hạn chế Data URL, lạm dụng Unicode, bảo vệ bài đăng/bình luận (số lượng bình luận/trả lời/thời gian), bảo vệ siêu quản trị viên, địa chỉ email người gửi
  • •UI công tắc toggle — tất cả các mục có/không được chuyển thành toggle (cài đặt cơ bản + bổ sung)
  • •Khóa dịch — khoảng 300 khóa, 13 ngôn ngữ

Fixed

  • •Lỗi SQL thùng rác — ràng buộc LIMIT ? chuỗi → số nguyên literal
  • •Summernote không render — tải jQuery/Summernote JS + khởi tạo sau khi hiển thị modal
  • •Lỗi collation — chỉ định rõ COLLATE utf8mb4_unicode_ci khi JOIN board_admins
  • •Thu/mở không hoạt động — hàm toggleSection được định nghĩa trước trong <head>

Changed

  • •Tab độc lập (danh sách/nâng cao) → tích hợp vào tab cài đặt cơ bản với thu/mở
  • •Chọn skin → chuyển sang tab cài đặt cơ bản; tab skin chỉ hiển thị cài đặt
  • •Email quản trị → đổi thành "Địa chỉ email người gửi" trong cài đặt nâng cao
  • •Quản trị viên module → chuyển sang tab phân quyền
  • •"Hiển thị danh mục trong danh sách" → xóa khỏi cài đặt danh mục, ủy quyền cho cài đặt theo skin
  • •"Hiển thị danh mục trong danh sách" → xóa khỏi cài đặt danh mục, ủy quyền cho cài đặt theo skin
  • •Nhóm được phép viết → tải động từ bảng rzx_member_grades thay vì hardcode
v1.6.0 2026-03-17 · 7 tháng trước

Added

  • •Hệ thống dự phòng đa ngôn ngữ: chuỗi fallback tích hợp trong db_trans() (ngôn ngữ đã cấu hình → en → ngôn ngữ mặc định → source_locale → bất kỳ bản dịch nào)
  • •Nút đa ngôn ngữ trong cài đặt bảng: nút đa ngôn ngữ (địa cầu) được thêm vào 6 trường trong tab cài đặt cơ bản
  • •Dự phòng đa ngôn ngữ trong giao diện bảng: áp dụng đa ngôn ngữ cho tiêu đề, mô tả, SEO, header/footer trong _init.php
  • •Dự phòng đa ngôn ngữ widget: cải thiện xử lý chuỗi rỗng trong WidgetRenderer::t(), tBtn()
  • •Thêm khóa dịch PWA (13 ngôn ngữ: admin.pwa.update_available, update, later)

Fixed

  • •Vấn đề thẻ trống của widget Features: toán tử ?? coi chuỗi rỗng "" là giá trị hợp lệ → sửa bằng fallback dựa trên !empty()
  • •Lỗi Mixed Content trên môi trường production: APP_URL http→https đã sửa + tự động sửa giao thức JS
v1.5.2 2026-03-17 · 7 tháng trước

Added

  • •Xóa dịch vụ từ lịch sử dịch vụ POS (nút xóa + API + cập nhật DOM tức thì)
  • •Thêm khóa dịch xóa dịch vụ cho 13 ngôn ngữ
v1.5.0 2026-03-17 · 7 tháng trước

Added

  • •Hệ thống tiếp nhận tại kiosk: xác nhận dịch vụ → thông tin khách hàng → tạo đặt chỗ → cấp số thứ tự
  • •Huy hiệu trạng thái sẵn sàng của nhân viên: hiển thị đang bận/sẵn sàng theo thời gian thực khi chọn nhân viên tại kiosk
  • •Mô-đun số điện thoại quốc tế: áp dụng thành phần phone-input vào biểu mẫu tiếp nhận tại kiosk
  • •Seed dữ liệu mẫu đặt chỗ: database/seed_reservations.php (10 bản ghi POS/kiosk/trực tuyến)
  • •Tách các tệp dùng chung của kiosk (_styles.php, _bg.php, _scripts.php)
  • •Thêm 11 khóa dịch kiosk cho 13 ngôn ngữ

Changed

  • •Chọn dịch vụ tại kiosk: lọc theo kỹ năng của nhân viên (chế độ chỉ định)
  • •Căn giữa các tab danh mục của kiosk

Fixed

  • •Không thể đăng nhập quản trị trên môi trường production (hỏng hash mật khẩu — sự cố thay thế biến $ của bash)
  • •Ổn định hệ thống cập nhật: mở rộng danh sách bảo toàn, kiểm tra tình trạng, đồng bộ phiên bản DB
  • •Hợp nhất nguồn phiên bản duy nhất (version.json → index.php, tự động đồng bộ DB)
VosCMS Cửa Hàng
Trang chủ Home 마켓플레이스 개발자 포털 Notice Free Board Q&A FAQ
Đăng nhập Đăng ký
Tiếng Việt
한국어 English 日本語 中文(中国) 中文(臺灣) Deutsch Español Français Монгол Русский Türkçe Tiếng Việt Bahasa Indonesia