Phase 6: Form (AcroForm) — liệt kê/điền/tạo field, flatten, FDF/CSV

Engine (form.rs MỚI):
- list_form_fields: duyệt cây /AcroForm/Fields (đệ quy /Kids), tên đầy đủ,
  phân loại theo /FT + cờ /Ff (text/checkbox/radio/combo/list/button/sig),
  đọc /V + options + on-state + trang + rect; kế thừa /FT từ cha
- fill_form_fields: text/combo đặt /V (UTF-16BE cho tiếng Việt), checkbox/radio
  đặt /V + /AS về on-state, bật NeedAppearances (portable mọi viewer)
- create_form_fields: tạo widget + field text/checkbox/combo, gắn vào /Annots
  + /AcroForm/Fields (tạo AcroForm nếu chưa có)
- flatten_form: PDFium page.flatten() in field vào nội dung, bỏ tương tác
- export_fdf/parse_fdf/import_fdf (literal ASCII + hex UTF-16BE round-trip
  tiếng Việt), export_csv

Tauri + UI (thanh 📝 Form):
- Commands: form_list, form_fill, form_flatten, form_create, form_export
  (FDF/CSV theo đuôi), form_import_fdf; pick_save_data/pick_fdf; tự chuẩn hoá
  qua qpdf khi lopdf không đọc thẳng trailer phi chuẩn (thêm dep lopdf cho app)
- 📋 Điền form (modal liệt kê field theo loại: text→ô nhập, checkbox→tick,
  combo→select), ➕ Thêm field (dialog loại/tên/trang/vị trí/cỡ/options),
  🧷 Flatten, ⬆ Xuất FDF/CSV, ⬇ Nhập FDF — không prompt/alert

Test (5 mới → engine 67/67 xanh ngoài 2 fixture qpdf Linux):
- create_and_list_fields; fill_text_checkbox_combo_round_trips (tiếng Việt);
  fdf_export_import_round_trip; export_csv_has_rows;
  flatten_removes_interactive_fields

Docs: 17-phase6-summary (+ giới hạn), 18-phase6-user-tests (F1–F10), README,
roadmap (Phase 6 HOÀN TẤT lõi), 14 (kế tiếp: Phase 7 OCR/Convert).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
This commit is contained in:
2026-07-15 16:52:51 +00:00
co-authored by Claude Fable 5
parent f62cded997
commit ccdb839fca
14 changed files with 1493 additions and 10 deletions
+4 -4
View File
@@ -50,11 +50,11 @@ Một ứng dụng desktop có thể **xem, chú thích, tổ chức trang, và
- Xoá metadata/ẩn; **chữ ký số** (PAdES, byte range, incremental update giữ chữ ký).
**DoD:** mã hoá/giải mã round-trip; redaction qua kiểm chứng không còn text bị bôi; ký số được Acrobat xác thực hợp lệ.
## Phase 6 — Form (AcroForm)
## Phase 6 — Form (AcroForm) ✅ HOÀN TẤT lõi (67/67 test — xem [docs/17-phase6-summary.md](17-phase6-summary.md))
**Mục tiêu:** Điền & tạo form.
- Điền form có sẵn, lưu; flatten form.
- Tạo field: text/checkbox/radio/dropdown/button; import/export dữ liệu (FDF/CSV).
**DoD:** điền & lưu giữ dữ liệu; tạo form mới mở được ở Acrobat; export/import round-trip.
- [x] Điền form có sẵn, lưu; flatten form.
- [x] Tạo field: text/checkbox/combo (radio-group/list/pushbutton: follow-up); import/export dữ liệu FDF + export CSV.
**DoD:** ✅ điền & lưu giữ dữ liệu (gồm tiếng Việt); tạo form mới; export/import FDF round-trip. Follow-up: XFDF, radio-group/list/pushbutton khi tạo.
## Phase 7 — OCR & Convert
**Mục tiêu:** Hai tính năng "đáng tiền" còn lại, qua dự án mở.
+8 -5
View File
@@ -101,7 +101,7 @@ Xếp theo mức độ ảnh hưởng trải nghiệm:
| Nhóm | Đường đi đã chốt trong roadmap | Rủi ro công nghệ |
|---|---|---|
| ~~Bảo mật, redaction, chữ ký số PAdES (Phase 5)~~ ✅ ĐÃ LÀM | AES-256+quyền, redaction thật (tỉa ký tự), **chữ ký số PKCS#7/CMS + xác thực + phát hiện giả mạo** (`sign.rs`), lưu tối ưu — 62/62 test | Đã giải; còn lại timestamp/LTV/PFX/multi-sig (docs/15 mục 6.6) |
| Form AcroForm (Phase 6) | PDFium có FPDF_FORMFILL đầy đủ (fill/flatten); tạo field mới bằng lopdf | Thấp-trung bình |
| ~~Form AcroForm (Phase 6)~~ ✅ ĐÃ LÀM | Liệt kê/điền/tạo field (lopdf) + flatten (PDFium) + FDF/CSV — 67/67 test (`form.rs`) | Đã giải; còn XFDF, radio-group/list/pushbutton khi tạo (docs/17 mục 6) |
| OCR (Phase 7) | Tesseract (tiếng Việt có traineddata chuẩn) + lớp text ẩn — kỹ thuật giống watermark.rs đã làm | Thấp, chủ yếu là chất lượng tiền xử lý ảnh |
| Convert Office↔PDF (Phase 7) | LibreOffice headless; PDF→Word "đủ dùng" trước | PDF→Word giữ layout hoàn hảo là bài khó với CẢ Foxit — đặt kỳ vọng "tương đương Foxit" chứ không hơn |
| So sánh PDF, in ấn, installer (Phase 8) | render diff đã có nền; Tauri bundler | Thấp |
@@ -136,13 +136,16 @@ redaction thật kiểm chứng được, xoá metadata — docs/15)**.
**Phase 5 đã HOÀN TẤT** (iter 1+2): mã hoá+quyền, gỡ mật khẩu, redaction thật
+ tỉa ký tự, xoá metadata, **chữ ký số PKCS#7/PAdES + xác thực**, lưu tối ưu.
**Phase 6 đã HOÀN TẤT lõi**: liệt kê/điền/tạo field, flatten, FDF/CSV.
Thứ tự đề xuất tiếp theo, bám giá trị người dùng:
1. **Phase 6 — Form (AcroForm)**: điền form (PDFium FPDF_FORMFILL), flatten,
tạo field text/checkbox/radio/dropdown, import/export FDF/CSV.
2. Phase 7 OCR/Convert → Phase 8 phát hành (theo roadmap).
1. **Phase 7 — OCR & Convert**: OCR Tesseract (Việt+Anh) tạo lớp text ẩn;
convert Office↔PDF qua LibreOffice headless; PDF→Word/Excel "đủ dùng".
2. Phase 8 — phát hành (installer, so sánh PDF, in ấn, đa ngôn ngữ UI).
3. Song song, rải theo từng phase: mở rộng font matching (3.4), nấc 1 của
hiệu năng phiên sửa (3.2) khi chạm file lớn thực tế, v2 của reflow
(justify/xoay — mục 3.1), và nâng chữ ký (timestamp/LTV/PFX/multi-sig).
(justify/xoay — mục 3.1), nâng chữ ký (timestamp/LTV/PFX/multi-sig), và
nâng form (XFDF, radio-group/list/pushbutton, appearance riêng).
## 6. Checklist FINAL TARGET & RULE cho chính tài liệu này
- [x] Đối chiếu từng tính năng với hành vi Foxit làm chuẩn nghiệm thu.
+67
View File
@@ -0,0 +1,67 @@
# 17 — Tổng kết Phase 6 (Form — AcroForm)
> Trạng thái: **HOÀN TẤT lõi.** Liệt kê / điền / tạo field, flatten,
> export/import FDF + export CSV. 5 test round-trip mới, tổng engine **67/67
> xanh** (ngoài 2 fixture qpdf Linux). Chi tiết & giới hạn ở mục 4–5.
## 1. Khảo sát Foxit (chuẩn nghiệm thu)
- **Fill & Sign / Form**: điền field có sẵn (text/checkbox/radio/combo/list),
lưu giữ dữ liệu; **Flatten** biến field thành nội dung tĩnh.
- **Prepare Form**: tạo field mới (text/checkbox/radio/dropdown/button).
- **Import/Export Form Data**: FDF/XFDF/CSV để trao đổi dữ liệu.
## 2. Lựa chọn kỹ thuật
- **Đọc/ghi cấu trúc AcroForm bằng `lopdf`** (thao tác tầng PDF object) —
portable, không cần khởi tạo form-environment của PDFium (vốn phức tạp và
phụ thuộc build). **Flatten dùng PDFium** (`page.flatten()`).
- Điền field đặt `NeedAppearances=true` để MỌI viewer tự dựng lại appearance —
cách tương thích rộng nhất, không phải tự vẽ appearance stream cho từng loại.
## 3. Đã làm — Engine (`form.rs`)
- **`list_form_fields`**: duyệt cây `/AcroForm/Fields` (đệ quy /Kids là field
con), suy tên đầy đủ (fully-qualified), phân loại theo `/FT` + cờ `/Ff`
(checkbox vs radio vs pushbutton; combo vs list), đọc `/V`, options, on-state
(tên trạng thái bật khác "Off" trong /AP /N), trang chứa widget + rect.
Kế thừa `/FT` từ cha cho field lá không tự khai.
- **`fill_form_fields`**: text/combo/list đặt `/V` (UTF-16BE cho tiếng Việt),
xoá `/AP` để dựng lại; checkbox/radio đặt `/V` + `/AS` widget về on-state;
bật NeedAppearances.
- **`flatten_form`**: PDFium flatten từng trang → in field vào nội dung, bỏ
tương tác.
- **`create_form_fields`**: tạo widget + field text/checkbox/combo (viền + nền
nhạt, /DA font mặc định), gắn vào `/Annots` trang + `/AcroForm/Fields`, tạo
AcroForm nếu chưa có.
- **FDF & CSV**: `export_fdf` (literal cho ASCII, hex UTF-16BE cho Unicode —
round-trip tiếng Việt), `parse_fdf`/`import_fdf` (parser đọc cả literal `(..)`
và hex `<..>`), `export_csv`.
## 4. Tauri + UI (thanh "📝 Form")
- Commands: `form_list`, `form_fill`, `form_flatten`, `form_create`,
`form_export` (FDF/CSV theo đuôi), `form_import_fdf`; picker
`pick_save_data`/`pick_fdf`. Mọi command tự chuẩn hoá qua qpdf khi lopdf
không đọc thẳng trailer phi chuẩn.
- **📋 Điền form**: modal liệt kê mọi field với input đúng loại (text→ô nhập,
checkbox→tick, combo→select) → Lưu & áp dụng ra file mới.
- **➕ Thêm field**: dialog chọn loại/tên/trang/vị trí/cỡ (+ options cho combo).
- **🧷 Flatten**, **⬆ Xuất FDF / CSV**, **⬇ Nhập FDF**.
- Không dùng prompt/alert; đếm số field hiển thị trên nút.
## 5. Test (5 mới → engine 67/67)
- `create_and_list_fields` — tạo 3 field (text/checkbox/combo) rồi liệt kê
đúng loại + options + trang + rect.
- `fill_text_checkbox_combo_round_trips` — điền (text tiếng Việt, checkbox bật,
combo chọn) rồi đọc lại đúng giá trị.
- `fdf_export_import_round_trip` — điền → export FDF → parse thấy giá trị →
import vào fixture rỗng → giá trị được điền lại (tiếng Việt đúng).
- `export_csv_has_rows` — CSV có header + dòng name,value.
- `flatten_removes_interactive_fields` — sau flatten không còn field tương tác.
## 6. Giới hạn (v-sau, không chặn dùng)
- Tạo field mới: hỗ trợ text/checkbox/combo; radio-group nhiều nút, list-box,
pushbutton (action) chưa tạo (đọc/điền thì được).
- Chưa vẽ appearance stream riêng → phụ thuộc NeedAppearances (Chrome/Foxit/
Acrobat đều dựng; vài viewer tối giản có thể không). Flatten khắc phục khi
cần bản “cứng”.
- Chưa XFDF (XML); mới FDF + CSV. Chưa validate/format (số, ngày) theo JS của
field. Điền trên UI qua danh sách (chưa overlay click trực tiếp lên trang —
cân nhắc cho vòng sau như edit-stage).
+35
View File
@@ -0,0 +1,35 @@
# 18 — Checklist test thủ công Phase 6 (Form)
Quan trọng nhất: **điền form lưu giữ dữ liệu** (F3) và **file mở đúng ở
Foxit/Adobe** (F4, F8), vì đây là dữ liệu người dùng nhập.
## Chạy
```powershell
cd c:\Project\FoFreeXit\app\src-tauri
cargo run
```
## Bảng test
| # | Thao tác | Kỳ vọng | KQ |
|---|----------|---------|----|
| F1 | Mở 1 PDF, bấm **📝 Form** | Hiện thanh Form; nút “Điền form (n)” cho biết số field | |
| F2 | Bấm **➕ Thêm field** → tạo 1 Text “hoTen” trang 1 → lưu | File mới mở lên, thanh Form đếm tăng | |
| F3 | Bấm **📋 Điền form** → nhập “Nguyễn Văn A” vào hoTen → Lưu | File mới; mở lại thấy giá trị đã điền | |
| F4 | Mở file F3 ở **Foxit/Adobe** | Field hoTen hiển thị đúng “Nguyễn Văn A” (tiếng Việt đúng dấu) | |
| F5 | Thêm 1 **Checkbox** và 1 **Combo** (Nam/Nữ/Khác) → Điền form: tick checkbox, chọn combo → Lưu | Mở lại: checkbox đang tick, combo đúng lựa chọn | |
| F6 | **⬆ Xuất FDF** → mở file .fdf bằng Notepad | Có tên field + giá trị (tiếng Việt dạng `<FEFF...>`) | |
| F7 | Trên 1 file form rỗng: **⬇ Nhập FDF** (chọn file F6) → Lưu | Các field được điền lại từ FDF | |
| F8 | **🧷 Flatten** file đã điền → mở ở Foxit | Giá trị vẫn hiển thị nhưng KHÔNG còn là field bấm/sửa được | |
| F9 | **⬆ Xuất CSV** → mở bằng Excel | 2 cột name,value đúng dữ liệu | |
| F10 | Mở form PDF THẬT (mẫu Acrobat) → **📋 Điền form** | Liệt kê đúng các field có sẵn, điền & lưu giữ được | |
## Mẫu phản hồi
```
[Mã] (vd F4) — Phần mềm mở: <Foxit/Adobe/Chrome> — Hiện tượng: <mô tả> —
Kỳ vọng: <...> — Ưu tiên: cao/vừa/thấp
```
> Giới hạn đã biết: tạo field mới hỗ trợ text/checkbox/combo (radio-group/
> list/pushbutton chưa tạo — đọc/điền thì được); dựa vào NeedAppearances để
> viewer dựng hình field (Flatten cho bản “cứng”); mới FDF+CSV, chưa XFDF —
> xem `docs/17-phase6-summary.md` mục 6.