Skip to main content

[DDD] Thiết kế Chi tiết Trang Tải lên Video

Tóm tắt tài liệu

Tài liệu này mô tả thiết kế kỹ thuật chi tiết cho Trang Tải lên Video (Upload Video Page). Đây là một quy trình nhiều bước phức tạp, cho phép người dùng tải lên một video, các hình ảnh liên quan, và điền vào một biểu mẫu siêu dữ liệu chi tiết được chia thành nhiều giai đoạn.

1. Tổng quan (Overview)

1.1. Bối cảnh và Vấn đề

Việc tạo một bài đăng bất động sản chất lượng đòi hỏi nhiều thông tin. Một biểu mẫu dài duy nhất sẽ gây choáng ngợp và khó sử dụng. Trang Tải lên giải quyết vấn đề này bằng cách chia quy trình thành ba bước logic, hướng dẫn người dùng qua từng giai đoạn một cách tuần tự và có xác thực tại mỗi bước.

1.2. Mục tiêu & Phi mục tiêu (Goals and Non-Goals)

Mục tiêu (Goals)

  • Cung cấp một quy trình tải lên gồm 3 bước với thanh tiến trình (StepProgressBar).
  • Bước 1: Cho phép tải lên tệp video (kéo-thả hoặc chọn tệp) và nhập thông tin cơ bản.
  • Bước 2: Nhập thông tin chi tiết về giá, diện tích, và các thuộc tính pháp lý.
  • Bước 3: Tải lên các hình ảnh bổ sung và chọn các tiện ích, dịch vụ.
  • Xác thực (validate) các trường bắt buộc ở mỗi bước trước khi cho phép đi tiếp.
  • Bắt đầu quá trình tải lên ở chế độ nền sau khi hoàn thành bước cuối cùng, cho phép người dùng điều hướng đi nơi khác.
  • Cung cấp phản hồi trực quan cho trạng thái tải lên thông qua UploadProgressContext.
  • Xử lý lỗi tải lên một cách an toàn, bao gồm cả việc cố gắng dọn dẹp dữ liệu không hoàn thiện (dữ liệu không còn được tham chiếu hoặc liên kết bởi bất kỳ thành phần nào khác trong cơ sở dữ liệu).

Phi mục tiêu (Non-Goals)

  • Chỉnh sửa video sau khi đã tải lên (ví dụ: cắt, ghép, thêm bộ lọc).
  • Tải lên nhiều video cùng một lúc.
  • Lưu bản nháp của biểu mẫu để hoàn thành sau.

2. Kiến trúc Tổng thể (Overall Architecture)

Component này là một máy trạng thái (state machine) phức tạp, điều phối giao diện người dùng, xác thực và các lệnh gọi API không đồng bộ.

Sequence Diagram - Luồng hoạt động Trang Tải lên Video

3. Thiết kế Chi tiết (Detailed Design)

3.1. Thiết kế Giao diện & Luồng người dùng (UI & User Flow)

Giao diện chính

Trang đăng video bao gồm nhiều bước, với các thành phần giao diện như:

  • UploadVideoPage: Giao diện tổng thể của quy trình đăng video.
  • StepProgressBar: Thanh thể hiện tiến độ theo từng bước (1 → 2 → 3).
  • BasicInfoForm: Biểu mẫu điền thông tin cơ bản (tiêu đề, mô tả, chọn video).
  • PriceAndAreaForm: Biểu mẫu điền thông tin về giá, diện tích và pháp lý.
  • AmenitiesAndServiceForm: Biểu mẫu chọn tiện ích, dịch vụ liên quan.
  • ImagePreview: Hiển thị ảnh đại diện/video đã tải lên.
  • VideoPreviewCard: Thẻ xem trước video đã chọn.

Luồng người dùng

Người dùng sẽ trải qua 3 bước để hoàn tất việc đăng video:

  1. Bước 1 - Nhập thông tin cơ bản

    • Người dùng truy cập vào trang đăng video.
    • Giao diện hiển thị ô chọn tệp video và một số ô để điền thông tin như tiêu đề, mô tả, v.v.
    • Khi người dùng nhấn "Tiếp theo", hệ thống sẽ kiểm tra xem các thông tin đã điền đầy đủ và hợp lệ hay chưa.
    • Nếu hợp lệ, hệ thống chuyển sang Bước 2.
  2. Bước 2 - Thông tin giá và pháp lý

    • Người dùng tiếp tục điền các thông tin liên quan đến giá cả, pháp lý hoặc điều kiện sử dụng.
    • Nhấn "Tiếp theo" để tiếp tục.
    • Hệ thống kiểm tra các thông tin một lần nữa. Nếu hợp lệ, sẽ chuyển sang Bước 3.
  3. Bước 3 - Hình ảnh & tiện ích

    • Người dùng tải lên hình ảnh đại diện và chọn các tiện ích liên quan.
    • Sau đó nhấn nút "Tải lên" để hoàn tất.
    • Hệ thống sẽ kiểm tra lại lần cuối toàn bộ thông tin. Nếu đầy đủ và hợp lệ:
      • Quá trình tải lên sẽ bắt đầu chạy ngầm (người dùng không phải chờ đợi).
      • Giao diện tự động chuyển về trang quản lý nội dung.
      • Một thông báo nhỏ hiển thị ở góc màn hình để báo rằng hệ thống đang xử lý.

⚠️ Nếu ở bất kỳ bước nào có thông tin chưa hợp lệ, người dùng sẽ được yêu cầu sửa trước khi có thể tiếp tục.

3.2. Luồng Tương tác (Interaction Flow)

3.3. Thiết kế API (API Design)

i. Tải lên Thông Tin Video

Tạo bản ghi video (metadata, thông tin chi tiết, v.v.) trong hệ thống backend.

Endpoint:

POST /brok/api/v1/content

Request Body:
Content-Type: application/json

{
"content_info": [
{
"lang": "vi",
"project_name": "[censored_project_name]",
"description": "[censored_description]",
"legal_certificates": "[censored_legal_certificates]",
"apartment_type": "[censored_apartment_type]",
"project_status": "[censored_project_status]",
"address": "[censored_address]",
"extra_description": ""
}
],
"price": "[censored_price]",
"unit_price": "[censored_unit_price]",
"area": "[censored_area]",
"unit_area": "[censored_unit_area]",
"geo": {
"lat": "[censored_lat]",
"long": "[censored_long]"
},
"profit_rate": {
"roi": "[censored_roi]",
"roa": "[censored_roa]"
},
"amenities": [
"[censored_amenity_1]",
"[censored_amenity_2]"
],
"isMultiLanguage": true
}

Response:
Trả về thông tin video đã tạo, bao gồm id (dùng ở các bước sau).

{
"success": true,
"message": "Content created successfully",
"data": {
id:"xxxxxx"
...
}
}

ii. Tải lên File Video (Video chính)

Tải file video chính (dữ liệu nhị phân) có liên kết với bài đăng bằng id.

Endpoint:

POST /file-processing/api/v1/upload?id={id}

Request Body:
Content-Type: multipart/form-data

Request Type POST with Content-Type: multipart/form-data


Summary

  • HTTP Method: POST
  • Content-Type: multipart/form-data; boundary=WebKitFormBoundaryDKfAqgwNHSmGgH7i
  • Query Parameter: id=xxxxxx
  • Form Field:
    • Field name: files
    • Filename: 1080fullhd1080fullhd.mp4
    • File type: video/mp4

  • file: File video cần upload.

Response:
Trả về thông báo tạo thành công.

{
"success": true,
"message": "Operation successful"
}

iii. Tải lên Media (Ảnh hoặc Tài liệu liên quan)

Tải lên các file bổ sung (ảnh, tài liệu, v.v.) có liên kết với bài đăng bằng id.

Endpoint:

POST /file-processing/api/v1/upload?id={id}&topic-key={topicKey}

Query Params:

  • id: ID của video (lấy từ bước 1).
  • topic-key: (Tùy chọn) Ví dụ "video_images_url" cho ảnh phụ.

Request Body:
Content-Type: multipart/form-data

  • files: Mảng file ảnh/media cần upload.

Response:
Trả về danh sách các URL media đã được lưu trữ.

[
{
"url": "xxx.jpeg"
}
]

Tóm Tắt Luồng Upload:

  1. Tạo thông tin video → Nhận ID.
  2. Tải file video chính kèm ID.
  3. Tải lên ảnh phụ kèm ID.

Ghi chú: Mỗi bước cần xử lý lỗi cụ thể (ví dụ như kiểm tra kích thước file, định dạng hợp lệ, timeout khi upload video lớn, v.v.)

3.4. Logic Xác thực (Validation Logic)

  • Các hàm xác thực (validateStep1Fields, validateStep2Fields, validateStep3Fields) được tách riêng để giữ cho code sạch sẽ.
  • Chúng nhận một hàm addError làm đối số, cho phép chúng thêm lỗi vào một đối tượng errors cục bộ.
  • Điều này cho phép hàm checkIsCurrentStepValid thu thập tất cả các lỗi cho bước hiện tại và trả về một kết quả boolean duy nhất.

4. Các yếu tố phi chức năng (Non-Functional Requirements)

4.1. Bảo mật (Security)

  • Xác thực tệp: Hàm isValidVideoFile kiểm tra MIME type của tệp để đảm bảo chỉ các định dạng video được hỗ trợ mới được chấp nhận, ngăn chặn việc tải lên các tệp độc hại.
  • Dọn dẹp khi có lỗi: Nếu việc tải lên thông tin thành công (tạo ra một bản ghi trong CSDL) nhưng việc tải tệp thất bại, hook useDeleteVideo được gọi để cố gắng xóa bản ghi đã tạo, tránh để lại dữ liệu không hoàn thiện.

4.2. Trải nghiệm người dùng (UX)

  • Phản hồi tức thì: Giao diện người dùng phản hồi ngay lập tức sau khi nhấn nút tải lên cuối cùng, điều hướng người dùng đi và hiển thị tiến trình trong một modal toàn cục (ProgressModal), mang lại cảm giác ứng dụng nhanh và không bị chặn.
  • Định dạng số: Hàm formatNumberValue tự động định dạng các số lớn (như giá tiền) bằng dấu phân cách hàng nghìn trong khi người dùng gõ, cải thiện khả năng đọc.
  • Kéo và Thả: Vùng tải lên video hỗ trợ kéo và thả tệp, cung cấp một cách tải lên thuận tiện.

5. Rủi ro và Phương án giảm thiểu (Risks and Mitigation)

Rủi roMức độ ảnh hưởngKhả năng xảy raPhương án giảm thiểu
Người dùng đóng tab/trình duyệt giữa chừng khi đang tải lênCaoTrung bìnhQuy trình tải lên nền hiện tại không thể sống sót sau khi đóng tab. Giải pháp: Sử dụng một Service Worker để quản lý việc tải lên hoàn toàn độc lập với vòng đời của trang. Đây là một nâng cấp lớn.
Lỗi không thể dọn dẹp dữ liệu không hoàn thiện trên serverTrung bìnhThấpTriển khai một công việc định kỳ (cron job) ở phía backend để tìm và xóa các bản ghi video không có tệp media liên quan sau một khoảng thời gian nhất định.
Quản lý state biểu mẫu phức tạp, dễ gây lỗiCaoCaoCân nhắc sử dụng một thư viện quản lý biểu mẫu chuyên dụng như React Hook Form hoặc Formik để đơn giản hóa việc quản lý trạng thái, xác thực và gửi dữ liệu, đặc biệt là cho các biểu mẫu phức tạp như thế này.

Tài liệu tham khảo: