โครงหน้าเว็บและการนำทาง (App shell & routing)
frontend ของ SML Ai Account เป็น Next.js 16 (App Router) + React 19 + Tailwind 4 ที่ build แบบ standalone
หน้าทำงานหลักมีหน้าเดียวคือ /home ซึ่งเป็น "พื้นที่ทำงานแบบหลายแท็บ" (MDI) ทุกจอบัญชีเปิดเป็นแท็บอยู่ข้างใน ไม่ได้แยกเป็น route ต่อจอ
ทำงานอย่างไร
เวอร์ชัน/เครื่องมือ (package.json:15-30): next ^16.3.1, react 19.2.1, tailwindcss ^4, lucide-react; next.config.ts:4 ตั้ง output: "standalone".
Next 16 ใช้ไฟล์ src/proxy.ts แทน middleware (export default proxy, proxy.ts:27).
ด่านแรก src/proxy.ts
- ไฟล์ static (รูป, ฟอนต์,
/imagesฯลฯ) ผ่านเลย (proxy.ts:31-41). - ถ้า host เป็นโฮสต์ smldemo (
isSmlDemoHost,proxy.ts:46) อนุญาตเฉพาะ path ในรายการSMLDEMO_ALLOWED_PATHS(proxy.ts:10-25) ที่เหลือ redirect ไป/home. - โฮสต์อื่น:
/loginเป็น public (proxy.ts:9,53); path อื่นต้องมี cookie เซสชัน (SESSION_COOKIE) ไม่งั้น redirect/login(proxy.ts:57-61). proxy ตรวจแค่ "มี cookie หรือไม่" ไม่ตรวจลายเซ็น - การตรวจจริงอยู่ที่getSession()ใน server layout (เซสชันและการยืนยันตัวตนฝั่ง frontend (Auth session & tokens)). matcherข้าม/apiและไฟล์ static (proxy.ts:66-70).
Server layout เป็นตัวกันสิทธิ์จริง
| ไฟล์ | พฤติกรรม |
|---|---|
src/app/page.tsx:8-12 |
/ redirect /home (ส่งต่อ ?open= ด้วยถ้ามี) |
src/app/(app)/layout.tsx:13-18 |
ไม่มี session -> /login; session.mode === "admin" -> /admin; ยังไม่เลือกฐานข้อมูล -> /select-database |
src/app/(app)/home/page.tsx:14-19 |
อ่าน session แล้วเรนเดอร์ WorkspaceRouteSync session autoOpen=?open= เปิดจอตรงจาก URL เช่น /home?open=menu_option |
src/app/(admin)/layout.tsx:16-27 |
เข้าได้เฉพาะ session.mode === "admin" หรือ demo viewer (isDemoCentralViewer) แล้วห่อด้วย AdminShell (หน้าจอผู้ดูแลระบบส่วนกลาง (Admin Console)) |
Root layout src/app/layout.tsx:76-103: ตั้ง lang="th", ค่า data-* ของธีม (theme/mode/density/edition ฯลฯ), สคริปต์ APPEARANCE_PREPAINT_SCRIPT กันภาพกระพริบ, แล้วห่อ AppearanceProvider > PersistentWorkspaceHost + GlobalLanguageTranslator + GlobalBalloonHelp (ตัวแปลภาษา th/en กับบอลลูนช่วยเหลือระดับทั้งแอป; ดูรายละเอียดในหัวข้อด้านล่าง).
PersistentWorkspaceHost (Keep-Alive) (shared/layout/PersistentWorkspaceHost.tsx)
WorkspaceModuleId(บรรทัด 104-120) คือโมดูลระดับบนที่ host รู้จัก (portal, home, pos, dashboard ฯลฯ).resolveModuleFromPath(บรรทัด 137-165) แมป pathname -> โมดูล:/homeที่มีopen=หรือsystem=account=home(พื้นที่บัญชี),/homeเฉยๆ =portal(SystemPortalScreenเมนูรวมระบบ).- โมดูลที่เคยเปิดเก็บไว้ใน
visitedModules(บรรทัด 258, 447-451) แล้วซ่อนด้วย CSShiddenแทนการ unmount (บรรทัด ~533) เพื่อให้สลับระบบแล้วข้อมูลในจอไม่หาย. - ใน host มีการ patch
window.fetch(บรรทัด 341-366): ถ้า response/api/*ตอบ 401 (ยกเว้น/api/auth/login|demo|google|logout) จะเรียกtriggerSessionExpiredแสดง modal "หมดเวลาใช้งาน" แล้วพาไป/login?returnTo=...(บรรทัด 290-298, 453-481) ใช้sessionStorage["sml_return_to"]จำหน้าเดิม. รายละเอียดเรื่อง returnTo ใน หน้าเข้าสู่ระบบและเลือกฐานข้อมูล (Login & select database). - โมดูล
homeเรนเดอร์TabWorkspace(พื้นที่ทำงานแบบแท็บ MDI และสิทธิ์จอ (TabWorkspace)); โมดูลportalเรนเดอร์SystemPortalScreen(รายการระบบอื่นของ ecosystem - นอกขอบเขตโน้ตชุดนี้).
Shell อื่น: shared/layout/AppShell.tsx:15-18 ห่อ Header + เนื้อหา; Header.tsx:42 มีลิงก์ไป /select-database (บรรทัด 243) และลิงก์สลับระบบอื่น (บรรทัด 63-79).
MenuBar.tsx:21-23 แบ่งหมวดสีเมนู 5 ประเภท master/daily/cancel/report/general (ข้อมูลหลัก/รายวัน/ยกเลิกเอกสาร/รายงาน/ข้อมูลทั่วไป) ด้วย getMenuCategory (บรรทัด 125).
Path alias ที่ต้องรู้ (tsconfig.json:44-47): @/components/layout/* -> shared/layout/*, @/components/ui/* -> shared/ui/*, @/components/* -> account/* (ใช้ตอน import จอบัญชี เช่น @/components/master/... = account/master/...), @/shared/*, @/account/*, @/* -> src/*.
ดังนั้น @/components/tabs/TabsContext = account/tabs/TabsContext.tsx.
ตัวช่วยระดับแอป (Global)
GlobalLanguageTranslator(shared/components/GlobalLanguageTranslator.tsx:253) ใช้พจนานุกรมTH_TO_EN_EXACTและtranslateThaiToEnglishในsrc/config/i18n/smlI18n.tsx:52,659เพื่อสลับข้อความไทย/อังกฤษ (SmlLanguage = "th" | "en", บรรทัด 7).GlobalBalloonHelp(shared/components/GlobalBalloonHelp.tsx:54) แสดงบอลลูนช่วยเหลือของช่องกรอก ใช้แคตตาล็อกsrc/config/help/smlFieldHelpCatalog.ts(ข้อมูลในsrc/config/help/data/*.json) และ route/api/help(เส้นทาง API ฝั่ง Next.js ที่ส่งต่อไป Go backend (API proxy routes)); เปิด/ปิดด้วยdata-balloon-helpบน<html>(ค่าเริ่มoff,layout.tsx:92).
ที่มาในโค้ด
frontend/src/proxy.ts:9-70- ด่าน cookie, smldemo allow-list, matcherfrontend/src/app/(app)/layout.tsx:13-18- redirect ตาม session/mode/databasefrontend/src/app/(admin)/layout.tsx:16-27- เฉพาะ mode admin หรือ demo viewerfrontend/shared/layout/PersistentWorkspaceHost.tsx:104-165,258,341-366,453-481- โมดูล, Keep-Alive, patch fetch 401frontend/tsconfig.json:44-47- alias@/components/*->account/*
ดูเพิ่ม
ภาพรวม Frontend ของ SML Ai Account (Frontend overview) · หน้าเข้าสู่ระบบและเลือกฐานข้อมูล (Login & select database) · เซสชันและการยืนยันตัวตนฝั่ง frontend (Auth session & tokens) · พื้นที่ทำงานแบบแท็บ MDI และสิทธิ์จอ (TabWorkspace) · หน้าจอผู้ดูแลระบบส่วนกลาง (Admin Console) · เส้นทาง API ฝั่ง Next.js ที่ส่งต่อไป Go backend (API proxy routes)