wal: flush 20260801T1317
This commit is contained in:
@ -55,9 +55,15 @@ chain:
|
||||
a11y-<a>-trong-label + O(n·m) FE (lớp K5-nợ) · CLARIFY menu-cache-re-login (UAT-NÓI-TRƯỚC).
|
||||
cicd-K7 ĐANG nền (sub-cicd-verify-k7.md — ĐÃ báo vai phủ-2-run vì 628132c đẩy chồng; restart×2
|
||||
= phép đo idempotent miễn phí)
|
||||
[!] GĐ3 cây-4-folder ĐỒNG-NHẤT — anh (55) "Nên đồng nhất": lane FE ĐANG nền @S167 (khuôn bfc7b79 S162
|
||||
3-trang + usePipelineStages-tập-contractIds K7 — sub-implfe-gd3.md, cửa chết ĐỌC FILE trước).
|
||||
CÒN SAU LANE: gate → commit → cicd
|
||||
[!] GĐ3 cây-4-folder ĐỒNG-NHẤT — anh (55) "Nên đồng nhất": lane FE trả BLOCKED-SẠCH @S167 (return CLEAN,
|
||||
0-file-chạm — sub-implfe-gd3.md 10.4KB): GĐ3 = 1-component-trang chung 7-loại (?type=N) NHƯNG layout
|
||||
3-panel cao-cố-định ≠ khuôn giấy-cuộn ⇒ prepend cột 19rem bóp panel-chi-tiết 346→42px @1366 (HỎNG
|
||||
CÂM build-xanh) · fe-admin sau K6 = deep-link-only · SHA-pair bất-khả cặp trang (khác tên khác ruột
|
||||
sẵn, 4-cặp-control dương). 🔴 CHỜ ANH 2 QUYẾT: (a) trang đích fe-user {MyContractsPage · InboxPage
|
||||
· WorkflowMatrixViewPage} + (b) phương án {A-prepend-42px⛔ · B-chỉ-≥2xl · C-nới-PipelineTreePanel-
|
||||
thu-gọn-desktop-GĐ3-mặc-định-ĐÓNG [lane+lead nghiêng C; C đụng 2-file-SHA-pair-chung-4-trang; câu phụ:
|
||||
mở = ĐẨY hay PHỦ] · D-cây-thay-Panel-3-khi-chưa-chọn}. Chốt xong lane scaffold 1 lượt → gate → commit
|
||||
→ cicd
|
||||
[ ] K8-prep form-14-người fail-closed + gói SOLUTION-PE-{n} + QĐ9 đo-2-nhánh + ZZTEST + rollback-theo-ID.
|
||||
🔴 (54) FINAL @S167 (anh, 2 lượt): "quy trình duyệt tử tế rồi ko sao" + "hiện cứ như vậy — Nếu điều
|
||||
chỉnh, tao sẽ tự tay điều chỉnh" ⇒ GIỮ HIỆN TRẠNG workflow/người-duyệt KHKK (8 WF N1-N8 đã seed @K3,
|
||||
|
||||
@ -23,11 +23,13 @@
|
||||
12. **Lọc client-side thì KHÔNG thêm trục vào `queryKey`** nếu payload đã tải trọn — thêm = N lần gọi mạng cho cùng một payload + N ô cache trùng. Ngược lại, trục làm ĐỔI request mà thiếu = cache dùng chung sai CÂM.
|
||||
13. **Muốn ĐẾM cái UI hiển thị thì DỰNG LẠI dữ liệu thật rồi chạy chính bộ lọc đã ship** — đừng đếm bằng mắt/suy luận. Và cho phép đo **tự kiểm**: cây menu dựng lại được đối chứng bằng invariant T6 (mọi key `MenuKeys.All` phải có menu-row) — dựng sai thì chỉ số đó vỡ trước.
|
||||
14. **Route-resolver có nhánh ≠ thứ đó tồn tại.** `resolvePath` nhận code `'Contract'` không có nghĩa menu-row `AwV2_Contract` tồn tại (0 hit repo). Cùng họ với "bịa field": đọc nhánh code rồi suy ra dữ liệu là suy ngược.
|
||||
15. 🔴 **Khuôn chỉ port được khi VỎ TRANG cùng hình dạng — đo BỀ NGANG bằng SỐ trước khi mirror.** Khuôn cột-trái `19rem` sinh ra cho trang GIẤY-CUỘN; trang 3-PANEL cao-cố-định (`h-[calc(100vh-4rem)]` + `grid-cols-[320px_1fr_360px]`, grid KHÔNG `gap`) không có 304px dư: sidebar `xl:w-80` ⇒ @1366 panel chi tiết 346px→**42px**. Mirror-y-hệt ở đây = hỏng CÂM (build xanh). Cộng bề ngang ra số TRƯỚC, và nhớ cơ chế thu gọn của component có thể là `lg:hidden` = chỉ sống ở dải mà panel kia đã ẩn ⇒ vô dụng ở desktop.
|
||||
|
||||
---
|
||||
|
||||
## 📌 Nhật ký (móc 1 dòng — verbatim → `archive/2026-H2.md`, cũ hơn → `archive/2026-H1.md` + `_INDEX.md`)
|
||||
|
||||
- **S167 (08-01) GĐ3** cây 4-folder lên cụm Duyệt-HĐ → **BLOCKED @§0, 0 file chạm**. 7 loại HĐ = 1 component trang (`?type=`), KHÔNG 7 file. 3 lệch tiền-đề: vỏ 3-panel không nhận khuôn cột-19rem (@1366 còn 42px) · fe-user có 3 ứng viên trang (`MyContracts`/`Inbox`/`WfMatrix`) vs admin 1 · cặp trang KHÁC FILE (`ContractsListPage`⟂`MyContractsPage`) ⇒ SHA-pair identical bất khả thi (đối chứng dương: 4 cặp component/hook/HardCopies BẰNG nhau). +K6 đã ẩn `Contracts` khỏi sidebar admin ⇒ nửa admin là trang deep-link-only. `[s167, khuon-can-cung-vo-trang, sub-implfe-gd3.md]`
|
||||
- **S166 (08-01) K6** admin thu gọn về vai NƠI-CONFIG (fe-admin ONLY 1 file, fe-user 0-diff). `filterForAdmin` lọc ĐỆ QUY ⇒ chỉ liệt 12 ROOT; **dựng lại cây seed 200 node rồi chạy bộ lọc đã ship ⇒ 166 lá → 15 lá liệt đủ tên**, tự-kiểm bằng invariant T6 (113 key `All` → 0 thiếu row). Comment vá lineage **2 lần đảo**. `[s166, k6-admin-thu-gon, route-resolver-khac-menu-row]`
|
||||
- **S166 (08-01) K4c** WfView lọc nhóm (chốt cụm-2, fe-user ONLY 1 file, fe-admin 0-diff). Lọc `wf.code === khkkGroupWorkflowCode(n)` client-side ⇒ **không đổi queryKey** (khai rõ); rỗng-vì-lọc tách câu riêng. 21/21 proof + 2 control-âm. `[s166, khkk-k4c-wfview-loc-nhom]`
|
||||
- **S166 (08-01) K5** cây toàn-trình GĐ2 mở **8 sub-folder nhóm** + forward-provision B3-A5. `groups` chia lại `leaves` phẳng ⇒ Σ theo cấu trúc; hiện đủ 8 kể cả rỗng + "(chưa phân nhóm)"; `lines[].contractId` KHÔNG tồn tại → union 1-nguồn + FLAG. 15/15 proof (CA4 tiêm lỗi). SHA 4/4 pair (2 đổi + **2 đứng yên = đối chứng dương**). `[s166, khkk-k5-8-sub-folder]`
|
||||
|
||||
@ -23,3 +23,105 @@ CICD-K7: IN-PROGRESS (đang đo — verdict ở dòng cuối)
|
||||
- Path-filter: có file `src/**` + `fe-*/**` ⇒ CI PHẢI chạy (không skip).
|
||||
|
||||
---
|
||||
|
||||
## M1 — Run Gitea 🔴 PHÁT HIỆN LỚN: run của `aaed699` bị **CANCELLED**, KHÔNG success
|
||||
|
||||
Đo lúc 13:09-13:10 qua `actions/tasks?limit=3` (khớp theo `head_sha`, KHÔNG theo run_number):
|
||||
|
||||
| run | head_sha | status | started | updated | ghi chú |
|
||||
|---|---|---|---|---|---|
|
||||
| **#441** (id 554) | **`aaed699`** | 🔴 **cancelled** | 13:04:57 | 13:07:59 | sống ~3m02s rồi bị **huỷ giữa chừng** |
|
||||
| **#442** (id 555) | `628132c` | running → (đo tiếp) | 13:08:26 | … | run-2 lead báo |
|
||||
| #440 (id 553) | `1c6d77a` | success | 11:54:38 | 12:01:07 | mốc PRE (K6) |
|
||||
|
||||
**Cơ chế:** push `628132c` lúc 13:08:26 ⇒ Gitea **cancel-in-progress** giết run #441 đang chạy.
|
||||
⇒ **Đề bài mục 1 ("run `aaed699` success") KHÔNG THOẢ THEO NGHĨA ĐEN** — `aaed699` chưa bao giờ tự deploy xong.
|
||||
|
||||
**Nhưng K7 VẪN ship, chứng minh bằng ancestry (không phải suy đoán):**
|
||||
- `git merge-base --is-ancestor aaed699 628132c` = **YES** ⇒ cây của run #442 CHỨA trọn 13 file K7.
|
||||
- `git diff --name-only aaed699..628132c` = 6 file (`docs/STATUS.md` · `fe-{admin,user}/…/KhkkWorkflowPanel.tsx` · 3 `scripts/*.ps1`) — không đụng file K7 nào.
|
||||
⇒ **run #442 = phương-tiện ship DUY NHẤT của K7.** Mọi phép đo POST vì thế quy về #442.
|
||||
|
||||
### 🔴 GOTCHA MỚI đề-xuất (#86) — "push-đè nuốt deploy im lặng"
|
||||
Push code A rồi push B ngay sau (<run-time của A) ⇒ run A **cancelled**. Nếu B **rơi trọn vào `paths-ignore`**
|
||||
(docs/memory-only) thì run B **skip** ⇒ **code A KHÔNG BAO GIỜ deploy**, mà bảng Actions trông vẫn "lành"
|
||||
(1 cancelled + 0 run) và `git log` thì đã push. Lần này thoát **NHỜ MAY**: `628132c` có chạm `fe-*/src/**`
|
||||
nên mới đẻ run. **Luật rút ra: sau 2 push liên tiếp, PHẢI xác minh run cuối cùng có head_sha là TIP và
|
||||
tip ⊇ commit code, chứ không được đọc "có run xanh" là xong.**
|
||||
|
||||
**Hệ quả cho mục 5 (restart-proof):** giả định "run-1 + run-2 = restart ×2 miễn phí" của lead **KHÔNG còn
|
||||
đúng** — run #441 bị giết TRƯỚC bước deploy nên **không hề restart pool**. Trong cửa sổ này chỉ có **1 lần
|
||||
restart thật** (từ #442). Idempotent-qua-2-restart do đó phải hạ cấp thành "chưa chứng-minh-được trong
|
||||
cửa-sổ" (xem M5) — tao KHÔNG tự restart pool prod (READ-only, cấm #6).
|
||||
|
||||
---
|
||||
|
||||
## M4-PRE — mốc bundle + tập marker (ĐO TRƯỚC khi deploy đè, 13:06-13:07)
|
||||
|
||||
**Bundle PRE (live, khớp đúng baseline K6 post-#440):**
|
||||
|
||||
| app | js | css | Last-Modified (GMT) | size js |
|
||||
|---|---|---|---|---|
|
||||
| admin | `index-Ig1R5tAh.js` | `index-DqXm5Hpn.css` | Sat 01 Aug 2026 **04:59:40** (=11:59:40 +07) | 1.758.853 B |
|
||||
| eoffice | `index-DFOCQ2ks.js` | `index-DlN3yZ5L.css` | Sat 01 Aug 2026 **05:00:41** (=12:00:41 +07) | 1.676.752 B |
|
||||
|
||||
**Kiểm-tra-tiền-đề cho marker (bài K6 nâng cấp — kiểm ĐƠN-VỊ-MÃ-HOÁ + ĐỊA-CHỈ trước khi tin 0-hit):**
|
||||
1. `file` báo bundle "ASCII text" ⇒ **nghi non-ASCII bị `\u`-escape**. Bác bỏ bằng đo: `grep -c -F 'Hợp đồng'`
|
||||
= **4**, `'Kế hoạch'` = **3** trên bundle PRE ⇒ tiếng Việt nằm **thô (UTF-8)**, `grep -F` đọc được. ✅
|
||||
2. **Nghi code-split** (nếu `KhkkDetailPage` nằm chunk lazy riêng thì marker 0-hit là vô nghĩa): index.html chỉ
|
||||
trỏ **đúng 2 asset** (`index-*.js` + `index-*.css`), và bundle **0 ref** dạng `"./xxx-<hash>.js"` ⇒ **single-bundle**, không lazy-chunk. ✅
|
||||
3. **CONTROL DƯƠNG** (chứng `KhkkDetailPage` THẬT nằm trong `index-*.js` + grep có răng) — 4 chuỗi bản **tiền-K7**
|
||||
của chính file đó, đo trên **cả 2** bundle PRE: `Phiếu nguồn chưa có NCC trúng thầu.`=1/1 ·
|
||||
`Chưa khai căn cứ nào.`=1/1 · `Giá tham chiếu (phiếu NCC)`=1/1 · `Tên TVGS xử lý`=1/1 ⇒ **4/4 hiện diện**. ✅
|
||||
|
||||
**CONTROL ÂM / tập marker K7 — 0-hit PRE trên CẢ 2 bundle (8/8, `grep -c -F`):**
|
||||
|
||||
| marker (chuỗi UI nút bridge) | adm PRE | eof PRE |
|
||||
|---|---|---|
|
||||
| `Đưa dòng kế hoạch vào Hợp đồng` | 0 | 0 |
|
||||
| `Chọn dòng đưa vào hợp đồng` | 0 | 0 |
|
||||
| `Loại hợp đồng` | 0 | 0 |
|
||||
| `Quy trình duyệt hợp đồng` | 0 | 0 |
|
||||
| `Phiếu chưa có dòng nhà cung cấp nào.` | 0 | 0 |
|
||||
| `khkk-bridge-line` | 0 | 0 |
|
||||
| `Tạo hợp đồng` | 0 | 0 |
|
||||
| `Chưa có giá chốt` | 0 | 0 |
|
||||
|
||||
⇒ marker có **tín hiệu thật** (0→≥1 mới là bằng chứng ship). Diff FE đối xứng: `fe-admin` và `fe-user`
|
||||
mỗi bên +308 dòng `KhkkDetailPage.tsx`, +61 `usePipelineStages.ts`, +49 `types/khkk.ts` (796 insert/40 delete tổng)
|
||||
⇒ kỳ vọng **element-wise 8/8 ở CẢ 2 app**.
|
||||
|
||||
---
|
||||
|
||||
## M3 — Migration (phần git, ĐÃ CHỐT) + prod PRE
|
||||
|
||||
- git: `1c6d77a..aaed699` **0 file** dưới `*Migrations*` ⇒ **0-mig**. (Range mở rộng tới `628132c` cũng 0 — 6 file kia không có Migrations.)
|
||||
- prod PRE (sqlcmd 13:06): `MIG_TOP` = `20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime` = **Mig 71** ✅ ·
|
||||
`sys.tables(is_ms_shipped=0)` = **97** ✅ · `MenuItems`=**200** · `Permissions`=**2221** (khớp anchor #438/#440).
|
||||
|
||||
---
|
||||
|
||||
## M5-PRE — trạng thái quyền `Contracts` TRƯỚC deploy (mấu chốt K7)
|
||||
|
||||
`SELECT COUNT(*) FROM Permissions WHERE MenuKey='Contracts' AND CanCreate=1` → **PRE = 1** ✅ (đúng dự-đăng-ký của gate-K7)
|
||||
`SELECT COUNT(*) … WHERE MenuKey='Contracts'` (mọi cờ) → **PRE = 13 row** (13 role, mỗi role 1 row)
|
||||
|
||||
Bảng đầy đủ 13 role PRE — `CanRead=1` **toàn bộ**, `CanCreate=1` **duy nhất Admin**:
|
||||
|
||||
| role | create | read | | role | create | read |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Accounting | 0 | 1 | | Equipment | 0 | 1 |
|
||||
| **Admin** | **1** | 1 | | Finance | 0 | 1 |
|
||||
| AuthorizedSigner | 0 | 1 | | HrAdmin | 0 | 1 |
|
||||
| CatalogManager | 0 | 1 | | **Procurement** | **0** | 1 |
|
||||
| CostControl | 0 | 1 | | ProjectManager | 0 | 1 |
|
||||
| DeptManager | 0 | 1 | | | | |
|
||||
| Director | 0 | 1 | | | | |
|
||||
| **Drafter** | **0** | 1 | | | | |
|
||||
|
||||
⇒ **Drafter + Procurement ĐÃ CÓ row sẵn** (read=1, create=0) ⇒ seeder phải **UPGRADE 2 row**, **KHÔNG add row nào**
|
||||
⇒ acceptance `0 added + 2 upgraded` **nhất-quán với trạng thái prod đo được**, và kỳ vọng POST:
|
||||
**CanCreate=1 → 3** đồng thời **tổng row `Contracts` GIỮ NGUYÊN 13** (nếu thành 15 ⇒ seeder add trùng ⇒ FAIL).
|
||||
Đọc code seeder xác nhận khuôn UPGRADE-ONLY: `SeedContractCreateAccessAsync` gọi **sau** revoker, chỉ nâng cờ, không hạ.
|
||||
|
||||
---
|
||||
|
||||
@ -0,0 +1,157 @@
|
||||
IMPLFE-GD3: BLOCKED
|
||||
|
||||
# Lane FE GĐ3 — áp cây 4-folder GĐ lên cụm "Duyệt hợp đồng"
|
||||
|
||||
Spawn: implementer-frontend @S167 (2026-08-01). Owner slot 55 "Nên đồng nhất".
|
||||
Rào: chỉ `fe-admin/src` + `fe-user/src`. KHÔNG BE, KHÔNG commit.
|
||||
|
||||
**Kết quả: BLOCKED tại §0 — 0 file chạm.** Không phải "không làm được", mà là: khuôn 3 trang
|
||||
kia KHÔNG PORT sang trang GĐ3 nếu không có 1 quyết định bố cục của em-main. Mirror y-hệt
|
||||
(prepend cột 19rem) là hỏng ĐO ĐƯỢC ở 1366 (số bên dưới), và hỏng CÂM — build vẫn xanh.
|
||||
|
||||
---
|
||||
|
||||
## §0 — ĐO ĐĨA (làm trước khi gõ; bài học #1)
|
||||
|
||||
### §0.1 Khuôn S162 `bfc7b79` áp lên trang HÌNH DẠNG NÀO
|
||||
|
||||
| Trang khuôn | Vỏ ngoài | Cách áp |
|
||||
|---|---|---|
|
||||
| `pe/PurchaseEvaluationsListPage.tsx` (GĐ1) | trang giấy-cuộn, đã CÓ cây trái riêng | nhét `PipelineStageFolders` vào TRONG cây sẵn có, `stage1Content` giữ nguyên khối leaf cũ |
|
||||
| `khkk/KhkkListPage.tsx` (GĐ2) | trang giấy-cuộn (`space-y`, thẻ card) | bọc `grid gap-5 lg:grid-cols-[19rem_minmax(0,1fr)] xl:grid-cols-[21rem_…]` + `<PipelineTreePanel currentStage={2}/>` |
|
||||
| `contracts/HardCopiesPage.tsx` (GĐ4) | trang giấy-cuộn | y hệt trên, `currentStage={4}` |
|
||||
|
||||
Neo đo: `fe-admin/src/pages/khkk/KhkkListPage.tsx:197` · `…/HardCopiesPage.tsx:116` — CẢ HAI
|
||||
là `grid gap-5 lg:grid-cols-[19rem_minmax(0,1fr)]`, tức **trang trôi theo chiều dọc, cột trái
|
||||
chỉ ăn bề ngang**.
|
||||
|
||||
### §0.2 Trang GĐ3 là trang nào (lead hỏi: 1 trang chung hay 7 file?)
|
||||
|
||||
**Trả lời: 1 COMPONENT TRANG dùng chung cho cả 7 loại HĐ, lọc bằng `?type=N` — KHÔNG phải 7 file.**
|
||||
Bằng chứng: `fe-user/src/components/Layout.tsx:143-153` regex `^Ct_([^_]+)_(List|Create|Pending|WfView|Approved|Deleted)$`
|
||||
→ mọi loại đều trỏ CÙNG 1 route + đổi query.
|
||||
|
||||
| App | File trang | Route | Leaf `Ct_*` trỏ tới | Vỏ ngoài |
|
||||
|---|---|---|---|---|
|
||||
| fe-admin | `pages/contracts/ContractsListPage.tsx` (254 dòng) | `/contracts` | `List` `Create` `Pending` (`Layout.tsx:117-125`) | 3-panel cao-cố-định |
|
||||
| fe-user | `pages/contracts/MyContractsPage.tsx` (231 dòng) | `/my-contracts` | `List` `Approved` `Deleted` | 3-panel cao-cố-định |
|
||||
| fe-user | `pages/InboxPage.tsx` (352 dòng) | `/inbox` | `Pending` (= đúng nghĩa "đang duyệt") | 3-panel + dải stats |
|
||||
| fe-user | `pages/pe/WorkflowMatrixViewPage.tsx` | `/contracts/workflow-matrix?type=3&ct=N` | `WfView` | dùng chung PE/KHKK |
|
||||
|
||||
fe-admin KHÔNG có `MyContractsPage`, KHÔNG có `InboxPage`, KHÔNG có `WorkflowMatrixViewPage`
|
||||
(cố ý — `Layout.tsx:138-142`).
|
||||
|
||||
### §0.3 🔴 Ba lệch so với tiền-đề đề bài
|
||||
|
||||
**A-1 (CHẶN — bố cục):** trang GĐ3 ×2 app KHÔNG phải trang giấy-cuộn. Cả 3 đều là
|
||||
`flex h-[calc(100vh-4rem)] flex-col` + `grid flex-1 overflow-hidden lg:grid-cols-[320px|340px_1fr_360px]`
|
||||
(`ContractsListPage.tsx:105,124` · `MyContractsPage.tsx:104,135` · `InboxPage.tsx:165,188`).
|
||||
Khuôn `19rem_minmax(0,1fr)` **không có chỗ cắm**: bọc grid ngoài thì cột trái cao 100vh cạnh
|
||||
một khối đã tự cuộn trong; prepend cột vào chính grid 3-panel thì:
|
||||
|
||||
> Sidebar app = `w-72` / `xl:w-80` (`Layout.tsx:499` user, `:372` admin) = 288/320px.
|
||||
> Grid 3-panel **không có `gap`** ⇒ cộng thẳng.
|
||||
>
|
||||
> | Bề ngang màn | Vùng nội dung | Panel 2 (chi tiết HĐ) HÔM NAY | Sau khi thêm cột cây 19rem (304px) |
|
||||
> |---|---|---|---|
|
||||
> | 1366 | 1046 | **346px** | **42px** ⛔ |
|
||||
> | 1536 | 1216 | 516px | **212px** ⛔ |
|
||||
> | 1920 | 1600 | 900px | 596px ✅ |
|
||||
>
|
||||
> Panel 2 render `ContractDetailContent` (form chi tiết HĐ đầy đủ). 42px = chết trang.
|
||||
> Chính khuôn S162 đã lo đúng bề ngang này: comment `KhkkListPage.tsx:198-200`
|
||||
> *"bảng 7 cột không thổi vỡ lưới ở 1366"*.
|
||||
|
||||
Cơ chế thu gọn có sẵn của `PipelineTreePanel` KHÔNG cứu được: nút "Hiện cây / Ẩn cây" là
|
||||
`lg:hidden` (`PipelineTreePanel.tsx:197`) — chỉ sống DƯỚI lg, tức đúng dải mà panel 2/3 đã bị
|
||||
`hidden lg:block`. Ở desktop panel luôn mở, không có chế độ đóng.
|
||||
⇒ **Đây là "thiếu prop cho GĐ3"** theo đúng ngoại lệ lead nêu, nhưng nới prop nào (`collapsible`?
|
||||
`defaultCollapsed`? mở ra thì ĐẨY hay PHỦ?) là quyết định UX ⇒ trả về em-main (refuse-criteria #1
|
||||
"page layout", anti-pattern #7).
|
||||
|
||||
**A-2 (CHẶN NHẸ — phạm vi):** "trang GĐ3" ×2 app không đối xứng. fe-admin có ĐÚNG 1 ứng viên
|
||||
(`ContractsListPage`); fe-user có 3 (`MyContractsPage` = danh sách · `InboxPage` = *Pending*,
|
||||
đúng nghĩa "đang duyệt" nhất · `WorkflowMatrixViewPage`). Khuôn cho mỗi GĐ đúng 1 trang ⇒ phải
|
||||
chốt trang nào. (Tôi nghiêng `MyContractsPage` — nó là cặp đối xứng của `ContractsListPage`.)
|
||||
|
||||
**A-3 (KHÔNG chặn — tiền-đề "SHA-pair identical" bất khả thi):** yêu cầu *"mirror ×2 app SHA-pair
|
||||
identical cho MỌI file chạm"* KHÔNG áp được cho cặp trang GĐ3: hai app dùng **file KHÁC TÊN,
|
||||
KHÁC RUỘT**, lệch sẵn từ trước, không phải do lượt này.
|
||||
|
||||
```
|
||||
792cc373… fe-admin/src/pages/contracts/ContractsListPage.tsx (254 dòng, có Select phase + phân trang)
|
||||
768728e3… fe-user/src/pages/contracts/MyContractsPage.tsx (231 dòng, có view "Đã xóa" + nút Tạo HĐ)
|
||||
```
|
||||
|
||||
Đối chứng DƯƠNG cho phép đo hash (cùng lệnh, cùng lượt, ra BẰNG NHAU — chứng phép đo không mù):
|
||||
|
||||
```
|
||||
d70ac315… = d70ac315… components/pipeline/PipelineTreePanel.tsx (admin = user)
|
||||
bed52f39… = bed52f39… components/pipeline/PipelineStageFolders.tsx (admin = user)
|
||||
76e18233… = 76e18233… hooks/usePipelineStages.ts (admin = user, ĐÃ gồm K7 aaed699)
|
||||
e4cb0bbb… = e4cb0bbb… pages/contracts/HardCopiesPage.tsx (admin = user, trang khuôn GĐ4)
|
||||
```
|
||||
|
||||
⇒ SHA-pair chỉ khả thi cho component/hook (vốn đã bằng). Với trang GĐ3 phải đổi sang bằng chứng
|
||||
`diff` khối chèn + khai lệch tại chỗ (bài học #10).
|
||||
|
||||
### §0.4 Bối cảnh mới hôm nay — fe-admin GĐ3 đã BỊ ẨN khỏi sidebar
|
||||
|
||||
`fe-admin/src/components/Layout.tsx:227-240` (K6 — S166, land HÔM NAY 2026-08-01):
|
||||
`ADMIN_HIDDEN_KEYS` chứa `'Contracts'` (GĐ3 root) + `'HopDongCung'` (GĐ4 root) + luật prefix
|
||||
`key.startsWith('Ct_')` (`:248`). `filterForAdmin` lọc ĐỆ QUY ⇒ **toàn bộ lối vào GĐ3 trên
|
||||
sidebar fe-admin đã chết**; `/contracts` chỉ còn vào được bằng deep-link.
|
||||
|
||||
Hệ quả cho lượt này: nửa fe-admin của việc là **trang không ai thấy trên menu**. Không sai (route
|
||||
còn sống, và tiền lệ `HardCopiesPage` fe-admin cũng đang ở đúng tình trạng đó từ K6), nhưng lead
|
||||
nên biết TRƯỚC khi trả công: "đồng nhất ×2 app" hôm nay ≠ "2 app cùng dùng được".
|
||||
|
||||
---
|
||||
|
||||
## §1 — 4 đường đi, để em-main chốt 1 chữ
|
||||
|
||||
| # | Cách | Panel 2 @1366 | Đụng file khuôn? | Ghi chú |
|
||||
|---|---|---|---|---|
|
||||
| **A** | prepend cột `19rem` vào grid 3-panel | **42px ⛔** | không | mirror chữ-nghĩa đúng nhất, hỏng thật |
|
||||
| **B** | cột cây chỉ hiện `≥2xl`, dưới đó ẩn hẳn | 346px (không có cây) | không | 1366/1536 = KHÔNG có cây ⇒ "đồng nhất" chỉ đúng ở màn to |
|
||||
| **C** | nới `PipelineTreePanel` +chế độ thu gọn desktop (nút "Cây toàn trình" ở đầu cột, GĐ3 mặc định ĐÓNG) | 346px khi đóng | **CÓ** (2 file SHA-pair) | đúng ngoại lệ "thiếu prop cho GĐ3"; còn 1 câu hỏi: mở ra thì ĐẨY panel hay PHỦ lên |
|
||||
| **D** | cây thay chỗ Panel 3 khi chưa chọn HĐ | 346px | không | Panel 3 đang là ô trống "Quy trình duyệt sẽ hiện khi chọn HĐ" ⇒ tận dụng chỗ đã trống, nhưng cây nhảy chỗ khi chọn HĐ |
|
||||
|
||||
**Tôi nghiêng C** (giữ được "đồng nhất" ở MỌI bề ngang, không cướp chỗ của chi tiết HĐ, và là
|
||||
lần nới prop DUY NHẤT dùng lại được cho `InboxPage` nếu sau này áp tiếp). Nhưng C sửa file
|
||||
SHA-pair dùng chung 4 trang khác ⇒ không tự quyết.
|
||||
|
||||
---
|
||||
|
||||
## §2 — UAT-NÓI-TRƯỚC (ghi sẵn cho lượt ship, chưa dùng tới)
|
||||
|
||||
- Prod hiện **0 HĐ** (lead khẳng định — tôi KHÔNG tự đo prod lượt này) ⇒ khi cây GĐ3 lên, mọi
|
||||
gói thầu sẽ hiện folder "Duyệt Hợp đồng" rỗng + chip **SẮP**. Đó là ĐÚNG SPEC, cùng lớp K5,
|
||||
không phải lỗi nối dữ liệu.
|
||||
- Phân biệt 2 cái im khác nhau: folder rỗng vì gói CHƯA có HĐ (chip SẮP) ⟂ folder **khoá** vì
|
||||
tài khoản không có quyền `Contracts`/`Ct_*_List` (`usePipelineStages.ts:58,328` — khoá thì
|
||||
KHÔNG gọi API). Đọc nhầm ổ khoá thành "chưa có dữ liệu" là bẫy quen.
|
||||
- Nguồn dữ liệu GĐ3 đã là TẬP `contractIds` (union `pe.contractId` legacy + `khkkPlanContractIds`)
|
||||
sau K7 — `usePipelineStages.ts:293-299`. Không cần sửa hook cho lượt GĐ3 này.
|
||||
|
||||
---
|
||||
|
||||
## §3 — Bằng chứng "0 chạm"
|
||||
|
||||
```
|
||||
$ git status --porcelain fe-admin/src fe-user/src
|
||||
(rỗng — xem §4 dòng chạy cuối)
|
||||
```
|
||||
Không chạy `npx tsc -b` / `npm run build`: 0 file thay đổi ⇒ build chỉ đo lại baseline của
|
||||
`aaed699`, không chứng minh được gì về lượt này. Đổi lại, `git status` rỗng là bằng chứng MẠNH
|
||||
HƠN cho "không để lại việc dở".
|
||||
|
||||
## §4 — Đã chạm / đã đo
|
||||
|
||||
- Đọc: `bfc7b79` (diff 3 trang khuôn) · `aaed699` (diff `usePipelineStages`) ·
|
||||
`PipelineTreePanel.tsx` · `PipelineStageFolders.tsx` · `usePipelineStages.ts` (bản đĩa, đã gồm K7) ·
|
||||
`ContractsListPage.tsx` · `MyContractsPage.tsx` · `InboxPage.tsx` (đầu file + grid) ·
|
||||
`Layout.tsx` ×2 app (khối `resolvePath` + `ADMIN_HIDDEN_KEYS`) · `App.tsx` ×2 app (routes).
|
||||
- Ghi: DUY NHẤT file artifact này.
|
||||
|
||||
END implfe-gd3 — VERDICT=BLOCKED (§0 chặn: A-1 bố cục 3-panel không nhận khuôn cột-19rem, số đo 1366 → Panel 2 còn 42px; A-2 fe-user có 3 ứng viên trang; A-3 cặp trang GĐ3 khác file nên SHA-pair identical bất khả thi). 0 file chạm. Cần em-main chốt 1 trong 4 đường ở §1 (tôi nghiêng C) + chốt trang đích ở A-2, rồi tôi scaffold trong 1 lượt.
|
||||
Reference in New Issue
Block a user