Thư viện biểu đồ SVG thuần (1/2 và 2/2)
Phần 1 (mục 1–7): đường, vùng, cột, donut, so sánh kỳ trước. Phần 2 (mục 8–16): gauge SLA, bullet SLA theo hàng đợi, heatmap thứ × giờ, phễu, histogram, sparkline KPI, radar nhân viên, thanh tiến độ mục tiêu, kết hợp cột + đường. Kỳ mẫu 04–10/10/2026 (60 cuộc gọi). Số liệu từ documents/spec/sample-data.json – DỮ LIỆU MẪU BỊA. Truy vết: FR-VIS (CR-T-017), FR-VIS-16, 18, 19, 20.
Quy ước chung
- Màu không phải kênh duy nhất: mỗi chuỗi có thêm kiểu nét + ký hiệu (đường: ● ■ ▲; nét liền/đứt/chấm) hoặc hoạ tiết nền (vùng, cột, donut: đặc, sọc chéo, chấm, lưới, sọc ngang) và nhãn giá trị.
- Co giãn: mọi SVG dùng
viewBox,width:100%. Dưới 520px, biểu đồ có trục cuộn ngang trong thẻ (không cuộn cả trang) để chữ không bị nhỏ quá; donut/pie co giãn trực tiếp. - Truy cập: mỗi SVG có
role="img"+<title>+<desc>; mỗi biểu đồ có mục “Xem bảng dữ liệu” là bảng đầy đủ cùng số liệu (caption,th scope). - Thay dữ liệu thật: mỗi biểu đồ có thuộc tính
data-source,data-ymax… và chú thích công thức toạ độ ngay dưới biểu đồ. Công thức chung:y = y0 − giá_trị × (chiều_cao_vùng_vẽ ÷ ymax). - Trạng thái: đang tải = khung xương (
.skeleton); rỗng = thông báo “Chưa có cuộc gọi trong kỳ” + gợi ý đổi bộ lọc; lỗi = thông báo + nút “Thử lại” (mẫu ở dashboard-states.html). Bảng thay thế luôn có sẵn để đọc bằng trình đọc màn hình.
1. Đường nhiều chuỗi – cuộc gọi theo ngày
Nguồn: trend_daily. Tổng / Đã nghe / Nhỡ, 04–10/10.
- Tổng cuộc gọi (nét liền, ●)
- Đã nghe (nét đứt, ■)
- Nhỡ (nét chấm, ▲)
Xem bảng dữ liệu (biểu đồ 1)
| Ngày | Tổng | Đã nghe | Nhỡ |
|---|---|---|---|
| CN 04/10 | 8 | 5 | 0 |
| T2 05/10 | 8 | 2 | 3 |
| T3 06/10 | 8 | 5 | 1 |
| T4 07/10 | 11 | 9 | 1 |
| T5 08/10 | 7 | 2 | 2 |
| T6 09/10 | 10 | 4 | 1 |
| T7 10/10 | 8 | 8 | 0 |
Thay dữ liệu: x = 70 + i×88,33; y = 250 − v×(228÷ymax); mỗi chuỗi một <polyline>, giữ nguyên kiểu nét + marker.
2. Vùng chồng – cơ cấu trạng thái theo ngày
Nguồn: daily_by_status. Chiều cao tổng mỗi ngày = tổng cuộc gọi.
- Đã nghe (đặc)
- Nhỡ (sọc chéo)
- Không trả lời (chấm)
- Máy bận (lưới)
- Lỗi kết nối (sọc ngang)
Xem bảng dữ liệu (biểu đồ 2)
| Ngày | Đã nghe | Nhỡ | Không trả lời | Máy bận | Lỗi kết nối | Tổng |
|---|---|---|---|---|---|---|
| CN 04/10 | 5 | 0 | 2 | 0 | 1 | 8 |
| T2 05/10 | 2 | 3 | 1 | 2 | 0 | 8 |
| T3 06/10 | 5 | 1 | 1 | 1 | 0 | 8 |
| T4 07/10 | 9 | 1 | 0 | 0 | 1 | 11 |
| T5 08/10 | 2 | 2 | 2 | 0 | 1 | 7 |
| T6 09/10 | 4 | 1 | 2 | 2 | 1 | 10 |
| T7 10/10 | 8 | 0 | 0 | 0 | 0 | 8 |
Thay dữ liệu: tính luỹ kế theo lớp, y = 250 − cum×(228÷ymax); mỗi lớp một <path> đi biên trên rồi quay lại biên dưới.
3. Cột đứng nhóm – kết quả theo hàng đợi
Nguồn: by_queue. Đã nghe / Nhỡ / Không trả lời cho 3 hàng đợi.
- Đã nghe (đặc)
- Nhỡ (sọc chéo)
- Không trả lời (chấm)
Xem bảng dữ liệu (biểu đồ 3)
| Hàng đợi | Đã nghe | Nhỡ | Không trả lời | Tổng cuộc |
|---|---|---|---|---|
| Bán hàng | 17 | 3 | 3 | 28 |
| Chăm sóc khách hàng | 11 | 3 | 3 | 20 |
| Kỹ thuật | 7 | 2 | 2 | 12 |
Thay dữ liệu: h = v×(228÷ymax), y = 250 − h, nhóm thứ j có tâm cx; ba cột lệch −60, −18, +24.
4. Cột chồng – trạng thái theo ngày
Nguồn: daily_by_status. Số trên đầu cột = tổng cuộc gọi trong ngày.
- Đã nghe (đặc)
- Nhỡ (sọc chéo)
- Không trả lời (chấm)
- Máy bận (lưới)
- Lỗi kết nối (sọc ngang)
Xem bảng dữ liệu (biểu đồ 4)
| Ngày | Đã nghe | Nhỡ | Không trả lời | Máy bận | Lỗi kết nối | Tổng |
|---|---|---|---|---|---|---|
| CN 04/10 | 5 | 0 | 2 | 0 | 1 | 8 |
| T2 05/10 | 2 | 3 | 1 | 2 | 0 | 8 |
| T3 06/10 | 5 | 1 | 1 | 1 | 0 | 8 |
| T4 07/10 | 9 | 1 | 0 | 0 | 1 | 11 |
| T5 08/10 | 2 | 2 | 2 | 0 | 1 | 7 |
| T6 09/10 | 4 | 1 | 2 | 2 | 1 | 10 |
| T7 10/10 | 8 | 0 | 0 | 0 | 0 | 8 |
Thay dữ liệu: mỗi đoạn <rect> có y = 250 − cum×(228÷ymax), height = count×(228÷ymax); bỏ đoạn bằng 0; nhãn tổng đặt ở y_đỉnh − 4.
5. Cột ngang xếp hạng – tỷ lệ nghe máy theo nhân viên
Nguồn: ranking, sắp giảm dần theo tỷ lệ nghe. Vạch đứt = mục tiêu mẫu 65% (goals, chờ xác nhận).
- Tỷ lệ nghe máy (đã nghe/tổng cuộc)
- Mục tiêu mẫu 65%
Xem bảng dữ liệu (biểu đồ 5)
| Hạng | Nhân viên | Đã nghe | Tổng cuộc | Tỷ lệ nghe | So với mục tiêu 65% |
|---|---|---|---|---|---|
| 1 | Đặng Ngọc Mai | 5 | 7 | 71,4% | Đạt |
| 1 | Đỗ Phương Linh | 5 | 7 | 71,4% | Đạt |
| 3 | Võ Quốc Bảo | 5 | 8 | 62,5% | Chưa đạt |
| 4 | Ngô Gia Huy | 4 | 7 | 57,1% | Chưa đạt |
| 5 | Bùi Thanh Tâm | 5 | 9 | 55,6% | Chưa đạt |
| 6 | Nguyễn Thị Lan | 7 | 13 | 53,8% | Chưa đạt |
| 7 | Hoàng Văn Khoa | 2 | 4 | 50,0% | Chưa đạt |
| 8 | Vũ Anh Tuấn | 2 | 5 | 40,0% | Chưa đạt |
Thay dữ liệu: sắp giảm dần; hàng thứ i có y = 10 + 30×i, width = % × 4; vạch mục tiêu tại x = 140 + mục_tiêu × 4.
6. Donut và pie – cơ cấu trạng thái, hướng gọi
Nguồn: status_breakdown (donut) và direction_split (pie).
- Đã nghe: 35 (58,3%)
- Nhỡ: 8 (13,3%)
- Không trả lời: 8 (13,3%)
- Máy bận: 5 (8,3%)
- Lỗi kết nối: 4 (6,7%)
Pie – hướng cuộc gọi
- Gọi đến (đặc)
- Gọi đi (sọc chéo)
Xem bảng dữ liệu (biểu đồ 6)
| Nhóm | Mục | Số cuộc | Tỷ lệ |
|---|---|---|---|
| Trạng thái | Đã nghe | 35 | 58,3% |
| Trạng thái | Nhỡ | 8 | 13,3% |
| Trạng thái | Không trả lời | 8 | 13,3% |
| Trạng thái | Máy bận | 5 | 8,3% |
| Trạng thái | Lỗi kết nối | 4 | 6,7% |
| Hướng | Gọi đến (10 được nghe) | 25 | 41,7% |
| Hướng | Gọi đi (25 được nghe) | 35 | 58,3% |
Thay dữ liệu: mỗi lát một <circle pathLength="100">; stroke-dasharray="p 100−p", stroke-dashoffset="−(tổng % lát trước)".
7. So sánh kỳ trước – tổng cuộc gọi theo ngày
Nguồn: prior_period.daily và trend_daily; mức thay đổi từ period_comparison. Kỳ này 04–10/10, kỳ trước 27/09–03/10 (cùng thứ trong tuần).
- Kỳ trước 27/09–03/10 (sọc chéo, cột trái)
- Kỳ này 04–10/10 (đặc, cột phải)
- Tổng cuộc gọi▲ Tăng 5,3%60 so với 57
- Tỷ lệ nghe máy▼ Giảm 1,3 điểm %58,3% so với 59,6%
- Thời lượng trung bình= Không đổi415 giây so với 415 giây
- Cuộc gọi nhỡ▼ Giảm 20,0%8 so với 10 (giảm là tốt)
Xem bảng dữ liệu (biểu đồ 7)
| Thứ | Ngày kỳ trước | Kỳ trước | Ngày kỳ này | Kỳ này |
|---|---|---|---|---|
| CN | 27/09 | 7 | 04/10 | 8 |
| T2 | 28/09 | 9 | 05/10 | 8 |
| T3 | 29/09 | 8 | 06/10 | 8 |
| T4 | 30/09 | 8 | 07/10 | 11 |
| T5 | 01/10 | 10 | 08/10 | 7 |
| T6 | 02/10 | 7 | 09/10 | 10 |
| T7 | 03/10 | 8 | 10/10 | 8 |
| Tổng | 27/09–03/10 | 57 | 04–10/10 | 60 |
Thay dữ liệu: cặp cột cx−30 (kỳ trước) và cx+2 (kỳ này); mức thay đổi dùng %Δ = (nay − trước) ÷ trước, riêng tỷ lệ % dùng hiệu số điểm %.
8. Gauge – SLA nhấc máy ≤ 20 s (cuộc đến)
Nguồn: sla. SLA = cuộc ĐẾN chờ ≤ 20 s ÷ tổng cuộc đến (18/25). Mục tiêu mẫu 80% (chờ xác nhận Q7).
▼ Chưa đạt mục tiêu: thấp hơn 8,0 điểm %
- Giá trị thực tế (cung màu)
- Vạch mục tiêu
Xem bảng dữ liệu (biểu đồ 8)
| Chỉ số | Giá trị |
|---|---|
| Tổng cuộc đến | 25 |
| Chờ ≤ 20 giây | 18 |
| SLA | 72,0% |
| Mục tiêu (mẫu) | 80,0% |
| Chờ trung bình / tối đa | 12,0 s / 30 s |
Thay dữ liệu: f = pct ÷ 100, θ = π·(1 − f), điểm cuối cung x = 160 + 110·cosθ, y = 150 − 110·sinθ; vạch mục tiêu nối bán kính 95–125 tại f = target_pct ÷ 100.
9. Bullet – SLA theo hàng đợi so với mục tiêu
Nguồn: by_queue[].sla_pct. Nền xám 3 mức: dưới 60%, 60–80%, từ 80%. Vạch đen = mục tiêu 80%.
- Giá trị thực tế (thanh đặc)
- Mục tiêu 80%
- ▲ đạt mục tiêu · ▼ chưa đạt
Xem bảng dữ liệu (biểu đồ 9)
| Hàng đợi | Cuộc đến | Chờ ≤ 20 s | SLA | So với mục tiêu 80% |
|---|---|---|---|---|
| Q1 Bán hàng | 12 | 8 | 66,7% | ▼ −13,3 điểm % |
| Q2 Chăm sóc khách hàng | 8 | 7 | 87,5% | ▲ +7,5 điểm % |
| Q3 Kỹ thuật | 5 | 3 | 60,0% | ▼ −20,0 điểm % |
| Tổng | 25 | 18 | 72,0% | ▼ −8,0 điểm % |
Thay dữ liệu: độ dài thanh = sla_pct × 3,9; vạch mục tiêu tại x = 170 + target × 3,9; mỗi hàng đợi thêm cách 60px theo trục y.
10. Heatmap – số cuộc gọi theo thứ × giờ
Nguồn: heatmap_weekday_hour. Thang tuần tự 4 mức (0 / 1 / 2 / 3 cuộc), mỗi ô có nhãn số; chữ đổi màu theo nền để đạt tương phản AA (≥ 4,5:1) ở sáng và tối. Mỗi thứ chỉ có 1 ngày trong kỳ nên giá trị 0–3.
- 00 cuộc
- 11 cuộc
- 22 cuộc
- 33 cuộc trở lên
Xem bảng dữ liệu (biểu đồ 10)
| Thứ | 8h | 9h | 10h | 11h | 12h | 13h | 14h | 15h | 16h | 17h | Tổng |
|---|---|---|---|---|---|---|---|---|---|---|---|
| T2 05/10 | 1 | 1 | 0 | 0 | 0 | 1 | 3 | 2 | 0 | 0 | 8 |
| T3 06/10 | 1 | 1 | 3 | 0 | 0 | 0 | 2 | 0 | 1 | 0 | 8 |
| T4 07/10 | 1 | 1 | 1 | 3 | 0 | 1 | 2 | 1 | 1 | 0 | 11 |
| T5 08/10 | 1 | 0 | 2 | 0 | 0 | 0 | 3 | 1 | 0 | 0 | 7 |
| T6 09/10 | 0 | 1 | 1 | 2 | 0 | 0 | 2 | 2 | 1 | 1 | 10 |
| T7 10/10 | 1 | 3 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 8 |
| CN 04/10 | 2 | 0 | 1 | 0 | 0 | 1 | 2 | 0 | 2 | 0 | 8 |
| Tổng | 7 | 7 | 9 | 6 | 0 | 3 | 15 | 7 | 5 | 1 | 60 |
Thay dữ liệu: ô (c, r) có x = 51 + 54·c, y = 40 + 34·r; lớp h0…h3 chọn theo ngưỡng 0 / 1 / 2 / ≥3. Giữ nhãn số trong ô và bảng thay thế.
11. Phễu – từ cuộc gọi phát sinh đến ghi chú sau gọi
Nguồn: funnel. Độ rộng thanh tỷ lệ với số cuộc (60 = 100%).
- Số cuộc ở mỗi bước (nhãn: số cuộc · % trên tổng 60)
Xem bảng dữ liệu (biểu đồ 11)
| Bước | Số cuộc | % trên tổng | % so với bước trước |
|---|---|---|---|
| Cuộc gọi phát sinh | 60 | 100,0% | — |
| Kết nối được (không lỗi kết nối) | 56 | 93,3% | 93,3% |
| Nghe máy | 35 | 58,3% | 62,5% |
| Đàm thoại từ 60 giây | 34 | 56,7% | 97,1% |
| Có ghi chú sau gọi | 12 | 20,0% | 35,3% |
Thay dữ liệu: rộng = count ÷ count_đầu × 340, x = 370 − rộng ÷ 2; thêm bước = thêm 52px theo trục y và tăng chiều cao viewBox.
12. Histogram – thời lượng đàm thoại và thời gian chờ
Nguồn: duration_histogram (35 cuộc đã nghe) và wait_time_histogram (25 cuộc đến). Các khoảng được vẽ cách đều dù độ rộng thực khác nhau (xem bảng).
12a. Thời lượng đàm thoại
12b. Thời gian chờ của cuộc đến (ngưỡng SLA 20 s)
- 12a: số cuộc đã nghe (đặc)
- 12b: chờ ≤ 20 s – đạt SLA (đặc)
- 12b: chờ > 20 s – không đạt (sọc chéo)
- Đường trung bình / ngưỡng
Xem bảng dữ liệu (biểu đồ 12)
| Khoảng | Từ – đến (giây) | Số cuộc |
|---|---|---|
| <2 phút | 0–119 | 5 |
| 2–4 phút | 120–239 | 3 |
| 4–6 phút | 240–359 | 6 |
| 6–8 phút | 360–479 | 6 |
| 8–10 phút | 480–599 | 8 |
| 10–12 phút | 600–719 | 3 |
| ≥12 phút | từ 720 | 4 |
| Tổng | — | 35 |
| Khoảng | Số cuộc | Đạt SLA 20 s |
|---|---|---|
| 0–5 s | 7 | Đạt |
| 6–10 s | 9 | Đạt |
| 11–20 s | 2 | Đạt |
| 21–30 s | 7 | Không đạt |
| Tổng | 25 | 18 đạt (72,0%) |
Thay dữ liệu: y = 250 − count × 22,8 (12a) hoặc 200 − count × 18 (12b); vạch trung bình/ngưỡng đặt theo nội suy trong khoảng chứa nó. Khi khoảng có độ rộng khác nhau, luôn ghi rõ trong trục hoặc bảng.
13. Sparkline trong thẻ KPI – xu hướng 7 ngày
Nguồn: sparklines và period_comparison. Sparkline không có trục: số liệu chính và mức thay đổi bằng chữ nằm trong thẻ; dấu chấm = ngày cuối (10/10).
- Tổng cuộc gọi60▲ Tăng 5,3% so với kỳ trước
- Tỷ lệ nghe máy58,3%▼ Giảm 1,3 điểm %
- Thời lượng trung bình415 giây= Không đổi
- Cuộc gọi nhỡ8▼ Giảm 20,0% (giảm là tốt)
Xem bảng dữ liệu (biểu đồ 13)
| Ngày | Tổng cuộc gọi | Tỷ lệ nghe máy (%) | Thời lượng TB (giây) | Cuộc nhỡ |
|---|---|---|---|---|
| 04/10 | 8 | 62,5 | 394 | 0 |
| 05/10 | 8 | 25,0 | 99 | 3 |
| 06/10 | 8 | 62,5 | 452 | 1 |
| 07/10 | 11 | 81,8 | 465 | 1 |
| 08/10 | 7 | 28,6 | 359 | 2 |
| 09/10 | 10 | 40,0 | 492 | 1 |
| 10/10 | 8 | 100,0 | 403 | 0 |
Thay dữ liệu: x = 4 + 18,67·i, y = 32 − (v − min) ÷ (max − min) × 28 với min/max của chuỗi; thêm chuỗi = thêm một <li class="spark-kpi">.
14. Radar – so sánh hai nhân viên
Nguồn: radar_agents (điểm 0–100 theo 5 trục). Ví dụ: NV01 Nguyễn Thị Lan so với NV04 Hoàng Văn Khoa. Chỉ nên so sánh tối đa 2–3 người.
- NV01 Nguyễn Thị Lan (nét liền, ●)
- NV04 Hoàng Văn Khoa (nét đứt, ▲)
Xem bảng dữ liệu (biểu đồ 14)
| Nhân viên | Số cuộc | Tỷ lệ nghe | Thời lượng TB | Nhấc máy ≤10 s | Có ghi chú |
|---|---|---|---|---|---|
| NV01 Nguyễn Thị Lan | 100 (13 cuộc) | 53,8 (53,8%) | 69,0 (414 s) | 85,7 (85,7%) | 42,9 (42,9%) |
| NV04 Hoàng Văn Khoa | 30,8 (4 cuộc) | 50,0 (50,0%) | 19,8 (119 s) | 100 (100%) | 100 (100%) |
Thay dữ liệu: θ = −90° + 72°·k; x = 230 + 1,05·điểm·cosθ, y = 175 + 1,05·điểm·sinθ; đóng đa giác bằng cách lặp điểm đầu. Điểm chuẩn hoá theo scale_note trong dữ liệu mẫu.
15. Thanh tiến độ – mục tiêu kỳ
Nguồn: goals. Mục tiêu là số MẪU, chờ quản lý xác nhận (Q7). Thanh = thực tế ÷ mục tiêu; vạch đen = mục tiêu. Trạng thái luôn có chữ và ký hiệu.
-
Tỷ lệ nghe máy58,3% / mục tiêu 65%▼ Chưa đạt: 89,7% mục tiêu, còn thiếu 6,7 điểm %
-
SLA nhấc máy ≤ 20 s (cuộc đến)72,0% / mục tiêu 80%▼ Chưa đạt: 90,0% mục tiêu, còn thiếu 8,0 điểm %
-
Số cuộc đã nghe35 / mục tiêu 40 cuộc▼ Chưa đạt: 87,5% mục tiêu, còn thiếu 5 cuộc
-
Cuộc nhỡ (tối đa cho phép)8 / giới hạn 6 cuộc▲ Vượt giới hạn 2 cuộc (nhỏ hơn là tốt; vạch đen = giới hạn 6, toàn thanh = 8)
- Tiến độ thực tế (đặc)
- Vượt giới hạn (sọc chéo)
- Mục tiêu / giới hạn
Xem bảng dữ liệu (biểu đồ 15)
| Mục tiêu | Thực tế | Mục tiêu / giới hạn | Tiến độ | Trạng thái |
|---|---|---|---|---|
| Tỷ lệ nghe máy | 58,3% | 65% | 89,7% | ▼ Chưa đạt |
| SLA nhấc máy ≤ 20 s | 72,0% | 80% | 90,0% | ▼ Chưa đạt |
| Số cuộc đã nghe | 35 | 40 | 87,5% | ▼ Chưa đạt |
| Cuộc nhỡ (tối đa) | 8 | 6 | 133,3% giới hạn | ▲ Vượt giới hạn |
Thay dữ liệu: width = min(actual ÷ target, 1) × 100%; với lower_is_better dùng thang 0…max(actual, target) và đặt vạch tại target ÷ max. Cập nhật aria-valuenow/aria-valuetext.
16. Kết hợp cột + đường – số cuộc và tỷ lệ nghe máy theo giờ
Nguồn: hourly_distribution. Cột = số cuộc (trục trái 0–16); đường = tỷ lệ nghe máy % (trục phải 0–100%). Giờ 12:00 không có cuộc nên đường ngắt, không vẽ 0%.
- Số cuộc gọi (cột, trục trái)
- Tỷ lệ nghe máy % (đường, ▲, trục phải)
Xem bảng dữ liệu (biểu đồ 16)
| Giờ | Tổng cuộc | Đã nghe | Tỷ lệ nghe máy |
|---|---|---|---|
| 08:00 | 7 | 4 | 57,1% |
| 09:00 | 7 | 5 | 71,4% |
| 10:00 | 9 | 6 | 66,7% |
| 11:00 | 6 | 4 | 66,7% |
| 12:00 | 0 | 0 | — (không có cuộc) |
| 13:00 | 3 | 1 | 33,3% |
| 14:00 | 15 | 9 | 60,0% |
| 15:00 | 7 | 4 | 57,1% |
| 16:00 | 5 | 2 | 40,0% |
| 17:00 | 1 | 0 | 0,0% |
| Tổng | 60 | 35 | 58,3% |
Thay dữ liệu: cột x = cx − 18, cao = total × 14,25; điểm đường (cx, 250 − rate × 2,28); giá trị null thì ngắt đường, không vẽ về 0. Đổi ymax thì đổi hệ số 14,25 = 228 ÷ ymax.