Files
skt-vuetify-templates/docs/frontend-layering.md
T
skytek_xinliang 87fbc1dda8 docs: refresh project guidance and environment setup
Add env example defaults for Vite API and login settings, document
template structure and page creation flow, and align agent guidance with
current LLM development rules. Also allow committing the env example while
keeping local env files ignored.docs: refresh project guidance and environment setup

Add env example defaults for Vite API and login settings, document
template structure and page creation flow, and align agent guidance with
current LLM development rules. Also allow committing the env example while
keeping local env files ignored.
2026-05-05 14:29:52 +08:00

17 KiB
Raw Blame History

前端分層規則與目前結構

目的

這份文件只描述目前 repo 已經落地的前端分層與命名規則,讓後續新增檔案、搬移檔案、或重構時有一致判斷基準。

重點不是追求理想化架構,而是避免把舊名稱、過渡寫法、或已刪除的結構繼續當成規則。

目前專案的主要責任鏈如下:

  • router 決定 route 與 layout meta
  • App.vue 根據 route meta 組裝 app shell 與全域 UI
  • views 承接路由入口與頁面資料協調
  • components 承接 layout、page component、domain component 與較細的 UI 區塊
  • composables 承接可重用流程與 UI state
  • stores 承接跨頁狀態、快取與全域顯示狀態
  • services 承接 HTTP client、API 模組、token 與錯誤處理

目前目錄的責任邊界

src/router

目前路由集中在:

責任:

  • 定義 route 與 route meta
  • 指定頁面使用哪種 layout
  • 串接導航守衛

目前 meta.layout 已是 app shell 切換的正式入口:

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

目前仍偏厚的 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 區塊已集中到:

這一層的定位是:

  • 服務 PageLogin
  • 屬於 login 頁面家族
  • 不是全域 base library

3. components/base

目前 components/base 只剩下:

目前判斷原則很直接:

  • base 只放真正可跨頁重用、且不屬於特定 domain 的元件
  • 若元件只服務單一頁面家族或單一 domain,優先放回對應資料夾

4. components/layouts

目前 layout 實作集中於:

其中 main-layout/*MainLayout 底下拆出的骨架子元件:

layout 應只承擔:

  • app shell
  • drawer / app bar / favorites / breadcrumb 等框架 UI
  • 與 layout 視覺結構直接相關的互動

layout 不應承擔:

  • 頁面專屬業務流程
  • 特定 domain 的資料規則

5. components/maint

這個目錄目前是最接近 feature folder 的區域,放 maintenance 領域的 page component 與 domain component

master-detail/* 目前屬於維護頁專用的較細組件群:

結論:

  • components/maint 主要扮演 maintenance domain component 層
  • CommonConfirmDialog 可以直接在 maintenance 頁或元件使用,不需要再包一層 CRUD dialog aggregator
  • 若只是維護頁專用子元件,不要搬到 base

src/composables

目前已明確分成兩組:

  • composables/layout/*
  • composables/maint/*

代表性檔案:

composables 的責任:

  • 放可重用流程
  • 放可測試的 UI state
  • 放與模板結構耦合較低的狀態機

src/stores

目前 store 已經是正式分層的一部分,而不只是暫時狀態容器。

代表性檔案:

責任:

  • 承接跨頁共享狀態
  • 承接畫面快取與顯示狀態
  • 作為 view 與 services 之間的狀態收斂點

規則:

  • store 檔案直接放在 src/stores/*.ts
  • 不要建立 src/stores/stores/* 這類重複巢狀目錄

src/services

services 現在已經是一層明確的資料存取邊界,不應再被視為附屬工具資料夾。

代表性檔案:

責任:

  • 提供 HTTP client
  • 封裝 API 模組
  • 統一 token、session 與錯誤處理

規則:

  • 元件不直接處理底層 HTTP 細節
  • 可共享的請求流程優先收斂到 store 或 composable,再由它們呼叫 service

目前已落地的分層模式

Template Core 與 Demo 邊界

Template Core

以下檔案屬於 template core,負責 app shell、layout、route、plugin、theme、HTTP 基礎設施與全域狀態:

  • main.ts
  • App.vue
  • src/router/index.ts
  • src/router/guards.ts
  • src/components/layouts/*
  • src/views/Login.vue
  • src/plugins/*
  • src/styles/*
  • src/services/client.ts
  • src/services/interceptors.ts
  • src/services/token.ts
  • src/services/session.ts
  • src/services/error.ts
  • src/services/http-error.ts
  • src/services/http-toast.ts
  • src/stores/auth.ts
  • src/stores/menu.ts
  • src/stores/breadcrumbs.ts
  • src/stores/favorites.ts
  • src/stores/messages.ts
  • src/stores/snackbar.ts
  • src/composables/layout/*

一般功能開發優先不要修改 template core;只有需求明確要求改變框架行為時才調整。

src/router/routes.ts 是新增功能 route 的正式入口,可新增 route,但不要破壞既有 layout meta、auth meta 與 catch-all route 規則。

Demo / Example

以下檔案偏向示範資料與範例頁,可在正式專案中替換或刪除:

  • src/views/Home.vue
  • src/components/PageIndex.vue
  • src/views/maint/*
  • src/components/maint/*
  • src/composables/maint/*
  • src/components/PageMaint.vue
  • src/stores/students.ts
  • src/stores/semesters.ts
  • src/views/FncPage.vue
  • src/views/Settings.vue
  • src/assets/logo.png
  • src/assets/logo.svg
  • src/assets/robot-svgrepo-com.svg

maint 是可參考的 demo feature,不是所有新專案都必須保留的核心功能。

移除 demo/example 時,要同步清理 routes、menu、language、store import、component import 與 assets。

模式 1view -> page component -> page family components

已落地頁面:

  • Login
  • Home

目前的穩定模式是:

  • view 負責資料準備與事件協調
  • page component 負責頁面主畫面組裝
  • 較細的視覺區塊再拆到對應頁面家族資料夾,例如 components/login/*

模式 2view -> 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 頁面。

模式 3router meta -> App.vue -> layout

這一層已正式成立:

  • route 決定 layout 類型
  • App.vue 決定套用哪個 shell
  • layout 專注在骨架與共用框架 UI

這代表 layout 的責任邊界不應再回頭混入頁面內部流程。

命名規則

頁面與 page component

  • 直接被 route 載入的檔案放 views
  • 負責完整頁面畫面組裝的元件,檔名用 Page 前綴
  • page component 不放進 base

目前例子:

資料夾命名

  • 多字資料夾一律使用 kebab-case
  • 不新增 snake_casePascalCase 資料夾

目前例子:

  • main-layout
  • master-detail

domain component 命名

  • 與特定領域強綁定的元件,優先用領域意圖命名
  • 不要為了抽象而保留含糊的舊前綴
  • 若元件只在 maint 領域使用,就留在 components/maint

目前仍待整理的區域

高優先度

原因:

  • 這些頁面仍保留較多頁面內資料轉換與事件協調

中優先度

  • 檢查 components/maint 內是否仍有可再明確命名的舊名稱
  • PageMaint 的後續演進,決定是否維持在 components 根目錄

中低優先度

  • 持續檢查 views 是否有可再下放到 page component 的模板片段
  • 清理命名調整後留下的空資料夾或死連結

新增或修改檔案時的判斷準則

  1. 這個檔案是否直接被 route 載入?
    • 是:優先放 views
  2. 這個檔案是否負責某個完整頁面的主畫面組裝?
    • 是:用 Page 前綴,放 page component 層,不要塞進 base
  3. 這段重複的是模板還是流程?
    • 模板:抽元件
    • 流程:抽 composable 或 store
  4. 這個狀態是否跨頁共享,或需要快取 / 全域顯示控制?
    • 是:優先考慮 store
  5. 這個邏輯是否在處理 API、token、session、錯誤正規化?
    • 是:放 services
  6. 這個元件是否只屬於單一 domain?
    • 是:優先放到該 domain 目錄,例如 components/maint
  7. 這個抽象是否真的降低重複與理解成本?
    • 否:不要抽