#standards#frontend#ux#lessons#bugs#transaction
บทเรียนบั๊ก UX/หน้าจอ (รอบตรวจ 2026-10-24)
ตารางบั๊กจริงที่แก้แล้ว พร้อมกฎสั้นๆ ที่ต้องจำเมื่อทำหน้าจอใหม่ ตัวเลข/เงินดู ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch) ส่วนสิทธิ์/ความปลอดภัยดู บทเรียนบั๊กสิทธิ์และการข้ามฐานข้อมูล (Auth Bypass, Cross-Tenant, Demo Read-Only, Screen Rights)
Modal, Session และธีม
| รหัส | อาการ | กฎ/วิธีแก้ |
|---|---|---|
| U1 | โหมดมืด backdrop กลายเป็นสีขาว; Esc ปิด Modal ทุกชั้นพร้อมกัน | ใช้ bg-slate-950/45; stack openModalStack (Modal.tsx:35) ให้ Esc ปิดเฉพาะชั้นบนสุด |
| U2 | แบนเนอร์ session หมดอายุอ่าน detail.error แต่ api-client ส่ง detail.message |
อ่าน detail.message ก่อน (PersistentWorkspaceHost.tsx) |
| U3 | ธีม/โหมดมืดใส่หลัง hydrate → กะพริบทุกครั้งที่รีเฟรช | สคริปต์ APPEARANCE_PREPAINT_SCRIPT ใน <head> (layout.tsx:62) — ดู กฎความปลอดภัยของ Animation: fill-mode, reduced motion และ Prepaint 3 จุด (Motion Safety Rules) |
| U4 | คลาส animate-in fade-in-0 zoom-in-95 ใช้ 22 จุดแต่ไม่มีปลั๊กอิน → ไม่มี animation |
ประกาศ @utility animate-in/fade-in-0/zoom-in-95 ใน globals.css |
| U5 | .sml-motion-card ใช้ animation … both ค้าง transform → การ์ดเป็น containing block ของ fixed child |
ใช้ backwards |
| D1 | Dashboard ค่าสำรองเป็นตัวเลขสมมติ | ?? 0 |
หน้าจอธุรกรรม (frontend/account/transaction/**)
- T1 ช่อง "กลุ่มเอกสาร" ผูกกับ
approveCodeทำให้doc_groupไม่เคยถูกบันทึก → ผูกกับdocGroupเท่านั้น - T2 (gl_journal) ไม่โหลด
book_codeตอนเปิดเอกสาร → แก้ JV A แล้วเปิด JV B บันทึก book code เปลี่ยนเงียบๆ → โหลดค่าของเอกสารนั้นทุกครั้ง - T3 ลบแถวสินค้าชุดแต่แถวย่อย (
set_ref_line) ค้างและถูกรวม → ลบแถวย่อยพร้อมกัน - T4 ปุ่ม "ค้นหาสินค้า" เขียนทับแถวสุดท้ายเสมอ → เพิ่มแถวใหม่ถ้าแถวสุดท้ายมีสินค้าแล้ว และอ่าน
itemLinesRefล่าสุด - T5
loadDocument(9 await) ไม่กันโหลดซ้อน → ผสมหัวเอกสาร B กับบรรทัด A แล้วบันทึกทับ → ตรวจ sequence หลังทุกawait - T6 จอที่ซ่อนในแท็บ MDI ยังรับ F12/Esc/Insert → ตรวจ
tabsApi.isActive(menuKey)และปิด hotkey ของรายการขณะisEditing(หมายเหตุ: ห้ามใช้ F-keys เป็นปุ่มบนจอ ดู ช่องกรอกมาตรฐานและกฎป้ายข้อความ (NumberBox, DateBox, CodeBox, LookupBox, ห้าม F1-F12)) - T7 ชื่อพนักงานขาย/แผนกเอกสารก่อนหน้าติดมาเอกสารใหม่, แก้เอกสารเดิมแล้วไม่โหลด GL/ภาษีใหม่, Rebuild GL ระหว่างแก้ไขทับข้อมูล → ล้าง/โหลดตามเอกสาร, reload หลังบันทึก, ซ่อนปุ่ม Rebuild ขณะแก้ไข
- T8 วันที่ ISO/ค.ศ.ตายตัว, ใช้
<input type="date">, ยอดจำนวนทศนิยม 2 ตำแหน่งตายตัว →formatSmlDate(),DateBox,item_qty_decimal,CommaNumberInput - T9
ItemHistoryModal.tsxjoinic_transไม่มีtrans_flag→ join ด้วยdoc_no+trans_flag - ใบรับวางบิลกันซ้ำด้วย
DISTINCT ON;row_keyฝั่ง client กันผล async ลงผิดแถว; ถามก่อนสลับเอกสารเมื่อแก้ค้าง (dirty snapshot)
Master / แท็บ MDI / รายงาน
- M1–M2 คีย์ลัด Insert/ลูกศร/Esc/Enter ในแท็บที่ซ่อนยังทำงาน → ไม่รับคีย์เมื่อ
rootRef.offsetParent === nullและSmlDialogฟังช่วง capture +stopPropagation - M3 รายการที่ไม่ส่ง
listKeyใช้คีย์ของแท็บที่ active → ใช้TabsContext.screenKeyต่อแท็บ - M4 สแกนบาร์โค้ด + Enter ใน 200ms เลือกแถวแรกของผลเก่า → รอผลใหม่ก่อนเลือก (
SmlLookupModal) - M5 พิมพ์รหัสใหม่แล้วชื่อเก่าค้าง (
SmlLookupInput) → ค้นชื่อใหม่ทุกครั้งที่รหัสเปลี่ยน - M6 ปุ่ม
+/ Insert / ดินสอ / ดับเบิลคลิกทิ้งข้อมูลที่กำลังแก้โดยไม่ถาม →confirmDiscard()ทุกจอ master (ใช้ในCustomerScreen,DealerScreen,CustomerDetailScreenฯลฯ) - M7 จอที่รหัสเป็น Lookup แก้รหัสบนรายการเดิมแล้ว UPDATE ใช้รหัสใหม่ใน WHERE → รหัสเป็น read-only เมื่อไม่ใช่รายการใหม่ (เว้นแต่มี
rowKey) - M8 ค่าเริ่มต้น "วันนี้" ใช้
toISOString()(UTC) ก่อน 07:00 ได้เมื่อวาน →todayLocal()(numeric.ts) - M9
BuySaleInformationScreenกรอง "เฉพาะมียอด" หลังLIMIT 100→ กรองใน SQL
ที่มา
docs/kms/KMS_SECURITY_DATA_INTEGRITY_LESSONS.mdตาราง U1–U5, D1, T1–T9, M1–M9, รอบที่ 2
ดูเพิ่ม
สารบัญมาตรฐานและกฎเหล็กของ SML Ai Account (Standards Overview) · การจัดเมนูตาม Workflow หน้าจอยกเลิกเอกสาร และ Lookup คลิกเดียว (Menu Workflow, Cancel Screens) · Header และ Toolbar 2 แถว ธีมการ์ด และสีพื้นหลัง Widget (EmployeeScreen Standard) · บทเรียนบั๊กสิทธิ์และการข้ามฐานข้อมูล (Auth Bypass, Cross-Tenant, Demo Read-Only, Screen Rights) · ภาพรวม Frontend ของ SML Ai Account (Frontend overview)