178 lines
8.7 KiB
Markdown
178 lines
8.7 KiB
Markdown
# PART 2 — biến thể `screen`
|
||
|
||
> **Dùng khi** `PRODUCT = screen` — sản phẩm có giao diện người dùng (web admin, web app,
|
||
> app di động). Cắm khối này vào chỗ PART 2 của [`../srs.md`](../srs.md).
|
||
>
|
||
> **Tiêu chí G3 riêng của biến thể này** *(thay cho dòng "bảng field" và "wireframe" ở
|
||
> [workflow.md §2](../../../ba-lifecycle/references/workflow.md))*:
|
||
> mỗi màn hình có bảng thành phần đủ 8 cột · mỗi field có bảng field đủ 10 cột · hai trạng
|
||
> thái rỗng khác nhau · mọi thành phần có điều kiện ẩn/khoá/read-only rõ ràng · **có `WF_<US>`
|
||
> (md + html) phủ mọi `SCR`, tập `C-id` khớp hai chiều, bảng lệch prototype ↔ SRS không còn
|
||
> dòng Tồn tại/Hành vi chưa quyết** · quy ước chung tham chiếu `UICONV_<PROJECT>`.
|
||
|
||
---
|
||
|
||
## 2.1 Danh sách màn hình
|
||
|
||
| ID | Tên màn hình | Loại | Đường dẫn | Vai trò truy cập | Vào từ đâu | Ra đi đâu |
|
||
|---|---|---|---|---|---|---|
|
||
| SCR-01 | | Danh sách / Chi tiết / Form / Modal | | | | |
|
||
|
||
Liệt kê **từng màn hình riêng**, kể cả modal và trang lỗi.
|
||
|
||
## 2.2 Sơ đồ điều hướng
|
||
|
||
<!-- archify: workflow · diagrams/SRS_<US>_dieu-huong.workflow.json -->
|
||
```mermaid
|
||
flowchart LR
|
||
MENU(["Menu"]) --> SCR01["SCR-01 Danh sách"]
|
||
SCR01 -->|chọn dòng| SCR02["SCR-02 Chi tiết"]
|
||
SCR01 -->|nút Tạo mới| SCR03["SCR-03 Form"]
|
||
SCR03 -->|lưu thành công| SCR01
|
||
SCR03 -->|huỷ / back| SCR01
|
||
SCR02 -->|back / breadcrumb| SCR01
|
||
```
|
||
|
||
*ID node khớp cột `ID` của bảng §2.1. Nhãn cạnh là **hành động gây điều hướng**.*
|
||
|
||
🔴 **Vẽ cả cạnh quay lại.** Sơ đồ chỉ có chiều đi là sơ đồ bỏ sót đúng phần hay lỗi nhất —
|
||
quay lại có giữ trạng thái danh sách không, huỷ giữa chừng thì đi đâu.
|
||
|
||
**Ba câu bắt buộc trả lời cho mỗi màn hình chi tiết/form:**
|
||
|
||
| Câu hỏi | SCR-02 | SCR-03 |
|
||
|---|---|---|
|
||
| Hai đường quay lại (nút back + breadcrumb)? Quay lại có giữ trạng thái danh sách (trang, bộ lọc)? | | |
|
||
| Vào bằng URL trực tiếp với id không tồn tại / không có quyền ⇒ hiện gì? | | |
|
||
| Rời màn hình khi form đang dở ⇒ có cảnh báo mất dữ liệu không? | | |
|
||
|
||
---
|
||
|
||
## 2.3 SCR-01 — <Tên màn hình>
|
||
|
||
**Bố cục:** `WF_<US>_v1.0.md` §3.x · `WF_<US>_v1.0.html#SCR-01` · prototype: *(frame/trang,
|
||
hoặc "✏️ BA tự dựng")*. Hành vi xem bảng bên dưới, không suy từ hình (W11).
|
||
|
||
### 2.3.1 Bảng thành phần
|
||
|
||
| ID | Tên thành phần | Loại | Nhãn (nguyên văn) | Placeholder / Hint | Hành vi & sự kiện | Điều kiện ẩn/khoá | BR |
|
||
|---|---|---|---|---|---|---|---|
|
||
| C01 | btn_create | Nút | Tạo mới | — | Mở SCR-03 | ❌ ẩn với ROLE-03 | |
|
||
| C02 | txt_search | Ô nhập | — | Nhập mã hoặc tên | Enter hoặc bấm Tìm mới gọi API | — | |
|
||
|
||
**Cột `Điều kiện ẩn/khoá` — chọn rõ một trong ba (quy tắc W7):**
|
||
|
||
| Ký hiệu | Nghĩa | Người dùng thấy gì |
|
||
|---|---|---|
|
||
| `❌ ẩn` | Không render | Không biết chức năng tồn tại |
|
||
| `🔒 disable` | Render, không bấm được, **có tooltip nêu lý do** | Biết có, biết vì sao chưa dùng được |
|
||
| `👁 read-only` | Hiện giá trị, không sửa được | Tra cứu được |
|
||
|
||
Ghi "tuỳ quyền" là **chưa đặc tả xong**.
|
||
|
||
### 2.3.2 Bảng dữ liệu hiển thị *(màn hình danh sách)*
|
||
|
||
| # | Cột | Nguồn dữ liệu | Định dạng | Sắp xếp được | Mặc định | Xử lý khi rỗng | Độ rộng |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 1 | Mã | `code` | Chữ hoa | ✅ | Sắp tăng | `—` | 120px |
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Sắp xếp mặc định** | |
|
||
| **Số dòng mỗi trang** | mặc định … · tuỳ chọn … |
|
||
| **Kiểu phân trang** | Offset / Cursor |
|
||
| **Bấm vào dòng** | Mở chi tiết / Không |
|
||
|
||
### 2.3.3 Bảng field *(màn hình có nhập liệu)*
|
||
|
||
| ID | Tên field | Kiểu | Bắt buộc | Độ dài / Khoảng | Default | Nguồn giá trị | Validation | Message khi sai | BR |
|
||
|---|---|---|---|---|---|---|---|---|---|
|
||
| F01 | | Text | ✅ | 3–20 ký tự (code point UTF-8) | — | Người dùng nhập | | `E-XXX-0001` | BR-0nn |
|
||
| F02 | | Chọn 1 | ✅ | — | | API `/…`, lọc `active=true`, sắp theo `order` | phải thuộc danh sách | `E-XXX-0002` | |
|
||
|
||
🔴 **Bốn cột không được để trống:**
|
||
|
||
| Cột | Nếu bỏ trống |
|
||
|---|---|
|
||
| **Độ dài/Khoảng** | DB nhận 255, UI không chặn ⇒ lỗi 500 khi dán đoạn dài. Ghi kèm **đơn vị** (ký tự? byte?) |
|
||
| **Default** | Mỗi màn hình một kiểu, báo cáo lệch vì bản ghi cũ null |
|
||
| **Nguồn giá trị** | Dropdown lấy từ đâu, **lọc theo gì**, **sắp xếp thế nào** |
|
||
| **Message khi sai** | Dev tự viết ⇒ mỗi màn hình một giọng, không dịch được |
|
||
|
||
### 2.3.4 Sơ đồ luồng *(bắt buộc khi hành động chạm ≥ 3 bên)*
|
||
|
||
*Chỉ vẽ khi luồng đi qua người dùng → giao diện → hệ thống → bên thứ ba, hoặc có bước bất
|
||
đồng bộ. Luồng đơn giản (bấm Lưu, gọi 1 API) thì bảng §2.3.5 là đủ.*
|
||
|
||
<!-- archify: sequence · diagrams/SRS_<US>_<luong>.sequence.json -->
|
||
```mermaid
|
||
sequenceDiagram
|
||
autonumber
|
||
actor U as Người dùng
|
||
participant FE as Giao diện
|
||
participant BE as Hệ thống
|
||
participant EXT as Hệ thống ngoài
|
||
|
||
U->>FE: Bấm Lưu
|
||
FE->>FE: Validate phía giao diện
|
||
FE->>BE: POST /… (khoá nút Lưu)
|
||
BE->>EXT: Kiểm tra … (timeout 3s)
|
||
alt Phản hồi kịp
|
||
EXT-->>BE: 200 OK
|
||
BE-->>FE: 200 + id
|
||
FE-->>U: Toast "Đã lưu", về danh sách
|
||
else Timeout / lỗi
|
||
EXT--xBE: timeout
|
||
BE-->>FE: 503 · E-XXX-0503
|
||
FE-->>U: Báo lỗi, GIỮ NGUYÊN dữ liệu đã nhập, mở lại nút Lưu
|
||
end
|
||
```
|
||
|
||
🔴 **Bắt buộc vẽ cả nhánh lỗi** (`alt`/`else`). Sequence chỉ có luồng thành công là vi phạm
|
||
quy tắc W4, và đó chính là nhánh dev hay tự bịa.
|
||
|
||
**Bảng đi kèm** *(quy tắc W13 — sơ đồ không nói được mã lỗi và ngưỡng)*:
|
||
|
||
| Bước | Mô tả | Timeout | Thất bại thì sao | Mã lỗi | AC |
|
||
|---|---|---|---|---|---|
|
||
| 3 | Gửi form lên hệ thống | 30s | Giữ dữ liệu, mở lại nút | `E-XXX-0503` | AC-09 |
|
||
| 4 | Kiểm tra với hệ thống ngoài | 3s | Cho lưu và đồng bộ sau / chặn? | | |
|
||
|
||
*Số ở cột **Bước** là số `autonumber` trong sơ đồ.*
|
||
|
||
### 2.3.5 Hành động trên màn hình
|
||
|
||
| Hành động | Điều kiện được phép | Xác nhận trước khi làm | Kết quả thành công | Kết quả thất bại | Vai trò | AC |
|
||
|---|---|---|---|---|---|---|
|
||
| Lưu | Form hợp lệ | Không | Toast + về danh sách | Giữ nguyên dữ liệu đã nhập, hiện lỗi | | AC-01 |
|
||
| Xoá | Trạng thái = Nháp | ✅ Modal + **nhập lý do** | Toast + xoá khỏi danh sách | Hiện lỗi, không xoá | | AC-07 |
|
||
|
||
🔴 **Thất bại phải giữ nguyên dữ liệu người dùng đã nhập.** Xoá trắng form sau lỗi mạng là
|
||
lỗi trải nghiệm nghiêm trọng và rất hay xảy ra khi spec không nói.
|
||
|
||
### 2.3.6 Trạng thái rỗng, đang tải, lỗi
|
||
|
||
*Cách trình bày (skeleton/spinner/banner) theo `UICONV` §6 — ở đây chỉ ghi **text riêng** cho
|
||
đối tượng của màn hình này và nút hành động. Trông thế nào, ở vùng nào: `WF` §3.x.3.*
|
||
|
||
| Trạng thái | Hiển thị gì | Text nguyên văn | Nút hành động |
|
||
|---|---|---|---|
|
||
| Đang tải | theo UICONV §6 | | |
|
||
| **Chưa có dữ liệu nào** | | "Chưa có bản ghi nào. Tạo bản ghi đầu tiên?" | ✅ Tạo mới |
|
||
| **Bộ lọc không khớp** | | "Không tìm thấy kết quả phù hợp với bộ lọc." | ✅ Xoá lọc |
|
||
| Lỗi tải dữ liệu | | | ✅ Thử lại |
|
||
|
||
🔴 Hai trạng thái rỗng **phải khác nhau**. Dùng chung một câu khiến người dùng tưởng mất dữ liệu.
|
||
|
||
---
|
||
|
||
## Lưu ý cho `PRODUCT = screen` + app di động B2C
|
||
|
||
Biến thể này viết cho phần mềm nghiệp vụ có vai trò. Với app tiêu dùng B2C, ba chỗ lệch:
|
||
|
||
| Chỗ | Điều chỉnh |
|
||
|---|---|
|
||
| `RBAC` ở GĐ2 | Thường chỉ 1–2 vai trò ⇒ ma trận gần như rỗng. Ghi rõ thay vì bỏ, và chuyển trọng tâm sang **phạm vi dữ liệu của chính người dùng** |
|
||
| Elicitation ở GĐ1 | Không phỏng vấn được hàng vạn người ⇒ dựa vào analytics + phỏng vấn sâu vài người + khảo sát |
|
||
| UAT ở GĐ4 | "Đúng người dùng thật" không scale ⇒ thay bằng **usability test 5–8 người + beta có giám sát**, tiêu chí pass đổi thành tỷ lệ hoàn thành tác vụ |
|