Update README and frontend layering docs to reflect the current template core structure, use relative repository links, and remove outdated demo guidance. Add expanded API response examples for common features and ignore local Codex configuration.docs: refresh template documentation and examples Update README and frontend layering docs to reflect the current template core structure, use relative repository links, and remove outdated demo guidance. Add expanded API response examples for common features and ignore local Codex configuration.
12 KiB
前端分層規則與目前結構
目的
這份文件只描述目前 repo 已經落地的前端分層與命名規則,讓後續新增檔案、搬移檔案、或重構時有一致判斷基準。
目前專案的主要責任鏈如下:
router決定 route 與 layout metaApp.vue根據 route meta 組裝 app shell 與全域 UIviews承接路由入口與頁面資料協調components承接 layout、page component、domain component 與較細的 UI 區塊composables承接可重用流程與 UI statestores承接跨頁狀態、快取與全域顯示狀態services承接 HTTP client、API 模組、token 與錯誤處理
目前目錄的責任邊界
src/router
目前路由集中在:
責任:
- 定義 route 與 route meta
- 指定頁面使用哪種 layout
- 串接導航守衛
目前 meta.layout 已是 app shell 切換的正式入口:
default走 MainLayout.vuenone走 PlainLayout.vue
src/App.vue
App.vue 目前不是單純掛載入口,而是實際的應用組裝層。
目前承擔的責任包含:
- 根據
route.meta.layout切換 layout - 組裝 breadcrumb / favorites / menu 等 layout props
- 放置全域搜尋結果 dialog
- 放置全域訊息中心 dialog
- 放置全域 snackbar
- 串接 layout event 與路由跳轉
判斷原則:
- 與整個 app shell 共享、且不屬於單一路由頁面的 UI,可留在
App.vue - 只屬於單一路由頁面的對話框或互動,不應堆到
App.vue
src/views
views 目前整體方向是「路由入口 + 頁面資料協調 + 頁面事件協調」。
目前較薄的 view:
- Home.vue
- Login.vue
- EditableGrid.vue
- Forbidden.vue
- ServerError.vue
- ServiceUnavailable.vue
- NetworkError.vue
- Maintenance.vue
- NotFound.vue
- ErrorShell.vue
- FncPage.vue
- Settings.vue
目前仍偏厚的 view:
views 應遵守的原則:
- 可以持有 route、store、頁面資料組裝、頁面事件協調
- 可以管理只屬於該頁的 dialog 顯示狀態
- 不應長期承擔大量可抽出的模板片段
- 不應把可重用流程直接留在頁面內重複複製
src/components
目前 components 已經分成幾種不同角色,不能再用單一規則描述。
1. 頁面型元件
目前以下元件實際上扮演 page component:
這些檔案的責任是:
- 接收 view 組好的資料與事件
- 組裝某個完整頁面的主畫面
- 再往下使用較小的子元件或 domain component
命名規則:
- 只要是 page component,檔名以
Page為前綴 - page component 可以放在
components根目錄 - 不要把 page component 丟進
base
2. components/login
登入頁的較細 UI 區塊已集中到:
- CreateAccountLink.vue
- LoginAnnouncementBoard.vue
- LoginBrand.vue
- LoginForm.vue
- LoginHeader.vue
- LoginIllustration.vue
- LoginToolBar.vue
- LoginVerify.vue
這一層的定位是:
- 服務
PageLogin - 屬於 login 頁面家族
- 不是全域 base library
3. components/base
目前 components/base 只剩下:
目前判斷原則很直接:
base只放真正可跨頁重用、且不屬於特定 domain 的元件- 若元件只服務單一頁面家族或單一 domain,優先放回對應資料夾
4. components/layouts
目前 layout 實作集中於:
- MainLayout.vue
- PlainLayout.vue
src/components/layouts/main-layout/*
其中 main-layout/* 是 MainLayout 底下拆出的骨架子元件:
- AppBarBreadcrumbCol.vue
- AppBarFavoritesCol.vue
- AppBarTopCol.vue
- DrawerDesktopMenu.vue
- DrawerMobileFavoritesPanel.vue
- DrawerMobileMenuPanel.vue
layout 應只承擔:
- app shell
- drawer / app bar / favorites / breadcrumb 等框架 UI
- 與 layout 視覺結構直接相關的互動
layout 不應承擔:
- 頁面專屬業務流程
- 特定 domain 的資料規則
5. components/maint
這個目錄目前是最接近 feature folder 的區域,放 maintenance 領域的 page component 與 domain component:
- PageMaint.vue
- CommonConfirmDialog.vue
- EditableGrid.vue
- MasterFileFormFields.vue
- MntDialogCard.vue
- MntRecordNavToolbar.vue
master-detail/*
master-detail/* 目前屬於維護頁專用的較細組件群:
- CourseMobilePanel.vue
- DetailCollapseGropus.vue
- DetailFullHeightPanel.vue
- DetailNavigation.vue
- DetailSidePanel.vue
- DetailSimpleList.vue
結論:
components/maint主要扮演 maintenance domain component 層CommonConfirmDialog可以直接在 maintenance 頁或元件使用,不需要再包一層 CRUD dialog aggregator- 若只是維護頁專用子元件,不要搬到
base
src/composables
目前已明確分成兩組:
composables/layout/*composables/maint/*
代表性檔案:
- useAdminLayoutState.ts
- useThemeToggle.ts
- useMaintenanceCrudFlow.ts
- useStudentMaintenanceForm.ts
- useEditableStudentGrid.ts
- useApiCall.ts
composables 的責任:
- 放可重用流程
- 放可測試的 UI state
- 放與模板結構耦合較低的狀態機
src/stores
目前 store 已經是正式分層的一部分,而不只是暫時狀態容器。
代表性檔案:
- auth.ts
- app.ts
- menu.ts
- breadcrumbs.ts
- favorites.ts
- messages.ts
- snackbar.ts
- loginAnnouncements.ts
- students.ts
- semesters.ts
責任:
- 承接跨頁共享狀態
- 承接畫面快取與顯示狀態
- 作為 view 與 services 之間的狀態收斂點
app.ts目前是空的 Pinia scaffold,尚未承擔實際 app state
規則:
- store 檔案直接放在
src/stores/*.ts - 不要建立
src/stores/stores/*這類重複巢狀目錄
src/services
services 現在已經是一層明確的資料存取邊界,不應再被視為附屬工具資料夾。
代表性檔案:
- client.ts
- interceptors.ts
- error.ts
- http-error.ts
- http-toast.ts
- session.ts
- token.ts
services/modules/*
責任:
- 提供 HTTP client
- 封裝 API 模組
- 統一 token、session 與錯誤處理
規則:
- 元件不直接處理底層 HTTP 細節
- 可共享的請求流程優先收斂到 store 或 composable,再由它們呼叫 service
目前已落地的分層模式
模式 1:view -> page component -> page family components
已落地頁面:
LoginHome
目前的穩定模式是:
view負責資料準備與事件協調- page component 負責頁面主畫面組裝
- 較細的視覺區塊再拆到對應頁面家族資料夾,例如
components/login/*
模式 2:view -> page component / domain components + maint composables
已落地區域:
views/maint/*components/maint/*composables/maint/*
這一層目前是 maintenance 領域最清楚的結構:
views/maint/*承接 route 與頁面流程協調- PageMaint.vue 承接維護頁共用頁面骨架
components/maint/*承接維護頁專用元件composables/maint/*承接 CRUD 流程、表單狀態與 editable grid 狀態
EditableGrid.vue 是目前最接近薄 view 的 maintenance 頁面。
模式 3:router meta -> App.vue -> layout
這一層已正式成立:
- route 決定 layout 類型
App.vue決定套用哪個 shell- layout 專注在骨架與共用框架 UI
這代表 layout 的責任邊界不應再回頭混入頁面內部流程。
命名規則
頁面與 page component
- 直接被 route 載入的檔案放
views - 負責完整頁面畫面組裝的元件,檔名用
Page前綴 - page component 不放進
base
目前例子:
資料夾命名
- 多字資料夾一律使用
kebab-case - 不新增
snake_case或PascalCase資料夾
目前例子:
main-layoutmaster-detail
domain component 命名
- 與特定領域強綁定的元件,優先用領域意圖命名
- 不要為了抽象而保留含糊的舊前綴
- 若元件只在 maint 領域使用,就留在
components/maint
新增或修改檔案時的判斷準則
- 這個檔案是否直接被 route 載入?
- 是:優先放
views
- 是:優先放
- 這個檔案是否負責某個完整頁面的主畫面組裝?
- 是:用
Page前綴,放 page component 層,不要塞進base
- 是:用
- 這段重複的是模板還是流程?
- 模板:抽元件
- 流程:抽 composable 或 store
- 這個狀態是否跨頁共享,或需要快取 / 全域顯示控制?
- 是:優先考慮 store
- 這個邏輯是否在處理 API、token、session、錯誤正規化?
- 是:放
services
- 是:放
- 這個元件是否只屬於單一 domain?
- 是:優先放到該 domain 目錄,例如
components/maint
- 是:優先放到該 domain 目錄,例如
- 這個抽象是否真的降低重複與理解成本?
- 否:不要抽