Files
goodgo-platform/docs/audits/IMAGE_QUICK_REFERENCE.md
Ho Ngoc Hai 11f2bf26e6
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
chore: update project documentation, audit reports, and initialize IDE configuration files
2026-04-19 03:12:54 +07:00

5.9 KiB

Hình Ảnh - Thẻ Tham Khảo Nhanh

🎯 Tổng Quan

Mục Trạng Thái Chi Tiết
Thẻ HTML <img> Tìm thấy 0 Tất cả đã được thay thế bằng next/image
next/image Đã Dùng 8 tệp Triển khai đúng cách trên toàn ứng dụng
Thành Phần Hình Ảnh 3 chuyên biệt Gallery, Lightbox, Upload
Cấu Hình Đã cấu hình remotePatterns + tiêu đề CSP
Khả Năng Tiếp Cận Hỗ trợ đầy đủ Văn bản thay thế, điều hướng bàn phím, ARIA
Bảo Mật Chỉ HTTPS CSP đã cấu hình, blob URL cho xem trước

📁 Vị Trí Sử Dụng Hình Ảnh

Thành Phần Hình Ảnh Cốt Lõi

components/listings/image-gallery.tsx      ← Trình xem thư viện chính
components/listings/image-lightbox.tsx     ← Xem toàn màn hình
components/listings/image-upload.tsx       ← Tải lên với xem trước

Các Thành Phần Hiển Thị Hình Ảnh

components/search/property-card.tsx        → Hình thu nhỏ trong kết quả tìm kiếm
components/agents/agent-profile-client.tsx → Ảnh đại diện + danh sách của môi giới
components/comparison/comparison-table.tsx → Hình ảnh so sánh
components/listings/listing-detail-client.tsx → Tích hợp ImageGallery

Thành Phần Trang

app/[locale]/(public)/listings/[id]/page.tsx       → Chi tiết tin đăng (dùng ImageGallery)
app/[locale]/(public)/search/page.tsx              → Kết quả tìm kiếm (dùng PropertyCard)
app/[locale]/(public)/agents/[id]/page.tsx         → Hồ sơ môi giới
app/[locale]/(dashboard)/listings/page.tsx         → Danh sách bảng điều khiển
app/[locale]/(dashboard)/listings/new/page.tsx     → Tải lên tin đăng mới

🔧 Cấu Hình

next.config.js

images: {
  remotePatterns: [
    {
      protocol: 'https',
      hostname: '**',
    },
  ],
}

Tiêu Đề CSP

img-src 'self' data: blob: https://*.mapbox.com https://*.tiles.mapbox.com https:
  • Cho phép blob: (xem trước tệp)
  • Cho phép data: (hình ảnh nội tuyến)
  • Cho phép tất cả HTTPS

📊 Chi Tiết Thành Phần Hình Ảnh

ImageGallery

<ImageGallery 
  media={propertyMedia}  // PropertyMedia[]
  className="w-full"
/>

Tính năng: Ảnh chính + hình thu nhỏ, điều hướng, bộ đếm, tích hợp lightbox

ImageLightbox

<ImageLightbox 
  images={images}
  initialIndex={0}
  open={isOpen}
  onClose={() => setIsOpen(false)}
/>

Tính năng: Điều hướng bàn phím, vuốt, tải trước, bẫy tiêu điểm

ImageUpload

<ImageUpload 
  images={uploadedImages}
  onChange={setUploadedImages}
  maxFiles={20}
/>

Tính năng: Kéo-thả, xác thực (JPEG/PNG/WebP), xem trước, dọn dẹp


🎨 Kiểu Dữ Liệu Hình Ảnh

interface PropertyMedia {
  id: string;
  url: string;              // URL hình ảnh
  type: 'image' | 'video';  // Loại phương tiện
  order: number;            // Thứ tự hiển thị
  caption?: string;         // Chú thích tùy chọn
}

interface ImageFile {
  file: File;               // Tệp trình duyệt
  preview: string;          // blob: URL
}

Tính Năng Hiệu Suất

Tính Năng Trạng Thái
Kích thước thích ứng (thuộc tính sizes) Đã triển khai
Tải ưu tiên cho nội dung phía trên nếp gấp Đã triển khai
Tải trước hình ảnh trong lightbox Đã triển khai
Dọn dẹp blob URL (bộ nhớ) Đã triển khai
Placeholder xương ⚠️ Chưa triển khai
Nén hình ảnh khi tải lên ⚠️ Chưa triển khai

Tính Năng Khả Năng Tiếp Cận

Tính Năng Trạng Thái
Văn bản thay thế trên hình ảnh Tiếng Việt
Nhãn ARIA Đã triển khai
Điều hướng bàn phím Phím mũi tên + Escape
Bẫy tiêu điểm trong hộp thoại Đã triển khai
Bẫy tab Đã triển khai

🔒 Danh Sách Kiểm Tra Bảo Mật

  • Mẫu remote chỉ dùng HTTPS
  • Tiêu đề CSP đã cấu hình
  • blob: URL chỉ dùng cho xem trước phía máy khách
  • ⚠️ Xác thực URL hình ảnh tại API - CẦN LÀM
  • ⚠️ Quét tệp tải lên của người dùng - CẦN LÀM

📝 Các Tác Vụ Thông Dụng

Thêm Hình Ảnh vào Thành Phần

import Image from 'next/image';

<Image
  src={imageUrl}
  alt="Văn bản mô tả bằng tiếng Việt"
  fill
  sizes="(max-width: 768px) 100vw, 50vw"
  className="object-cover"
/>

Hiển Thị Thư Viện Hình Ảnh

import { ImageGallery } from '@/components/listings/image-gallery';

<ImageGallery 
  media={property.media}
/>

Tải Lên Tệp

import { ImageUpload } from '@/components/listings/image-upload';

const [images, setImages] = useState<ImageFile[]>([]);

<ImageUpload 
  images={images}
  onChange={setImages}
  maxFiles={20}
/>

🚨 Lưu Ý Quan Trọng

  1. Không bao giờ dùng thẻ HTML <img> - Sử dụng next/image thay thế
  2. Ngoại lệ: Xem trước blob URL trong image-upload là chấp nhận được
  3. Luôn cung cấp văn bản thay thế - Dùng văn bản tiếng Việt
  4. Dùng thuộc tính sizes - Cho hình ảnh thích ứng
  5. Đặt priority - Cho hình ảnh phía trên nếp gấp
  6. Thu hồi blob URL - Khi huỷ gắn kết để ngăn rò rỉ bộ nhớ
  7. Xác thực URL hình ảnh - Tại lớp API trước khi trả về

📞 Câu Hỏi?

Xem IMAGE_AUDIT_REPORT.md để biết chi tiết đầy đủ và các khuyến nghị.