diff --git a/docs/add-page-example.md b/docs/add-page-example.md index fcd9a95..b5c4063 100644 --- a/docs/add-page-example.md +++ b/docs/add-page-example.md @@ -7,9 +7,9 @@ 目前新增一般頁面的預設資料流: ```txt -router -> view -> (page driver) -> page component -> sections/items - ↓ - store/composable -> service +router -> view -> sections/items + ↓ + composable -> store -> service ``` Page driver 不是必備層:若頁面邏輯只有簡單的 `computed` page model(無搜尋、無 dialog、無複雜事件協調),直接在 view 裡寫即可,不需要建立 page driver。 @@ -22,7 +22,6 @@ Page driver 不是必備層:若頁面邏輯只有簡單的 `computed` page mod - - -``` - 若畫面是固定的「篩選條件 + 查詢按鈕 + 結果表格」,優先使用 `components/sections/SectionQueryPage.vue`。若是「表單欄位 + 送出/存檔按鈕」,優先使用 `components/sections/SectionFormPage.vue`。 -## 3. 加入 route +## 2. 加入 route route 加在 `src/router/routes.ts` 的 `routes` 陣列中,並放在 `/:pathMatch(.*)*` catch-all route 前面。 @@ -125,7 +79,7 @@ route 加在 `src/router/routes.ts` 的 `routes` 陣列中,並放在 `/:pathMa - 新功能若使用後端選單,優先調整後端選單資料或對應 API mock,不要把頁面專屬選單邏輯塞進 layout。 - 若只是新增 route,通常不需要修改 `MainLayout.vue` 或 `src/shell/*`。 -## 4. 需要 API 時新增 service module +## 3. 需要 API 時新增 service module ```ts // src/services/modules/reports.ts @@ -148,7 +102,7 @@ service 只封裝 HTTP 細節,不持有 UI 狀態。 `httpClient` 的 `baseURL` 來自 `VITE_API_BASE_URL`,沒有設定時預設 `/service/api`。開發模式下,Vite proxy 會將 `/service/*` 轉送到 `VITE_PROXY_TARGET`。 -## 5. 需要共享狀態時新增 store +## 4. 需要共享狀態時新增 store 只有跨頁共享、需要快取、或全域狀態才新增 store。單頁暫時狀態留在 view、component 或 composable。 @@ -180,7 +134,7 @@ export const useReportsStore = defineStore('reports', () => { }) ``` -## 6. 驗證 +## 5. 驗證 至少執行: diff --git a/docs/architecture-strategy.md b/docs/architecture-strategy.md index 42fbc28..7ee804f 100644 --- a/docs/architecture-strategy.md +++ b/docs/architecture-strategy.md @@ -24,17 +24,11 @@ Read only when needed: [analyse now](./analyse-now.md) │ App Shell │ │ (App.vue → Layout → Global Overlays: Snackbar/Dialogs) │ └──────────────────────────┬──────────────────────────────────┘ - │ page model (reactive) + │ reactive / props ▼ ┌─────────────────────────────────────────────────────────────┐ -│ Page Driver │ -│ (views/*.vue — 極薄,只負責:組裝 page model / 事件轉發) │ -└──────────────────────────┬──────────────────────────────────┘ - │ props / emits - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ Page Component │ -│ (PageXxx.vue — 組裝完整頁面,決定 Section 順序與 override) │ +│ View │ +│ (views/*.vue — 自含 page model、頁面 UI 與 section 組合) │ └──────────────────────────┬──────────────────────────────────┘ │ section data ▼ @@ -58,7 +52,7 @@ Read only when needed: [analyse now](./analyse-now.md) ### 3.2 Page Model 作為主要資料單位 - **新增 `src/models/page.ts`**:定義各頁面的統一介面。 -- View 的職責從「管理資料 + 管理狀態 + 組裝模板」縮減為「呼叫 usePageDriver() 取得 page model,傳給 Page component」。 +- View 的職責從「管理資料 + 管理狀態 + 組裝模板」縮減為「呼叫 composable 取得 page model,組裝 section 元件」。 - Page model 可以來自: - store(已有快取) - service(直接 API) @@ -130,15 +124,11 @@ src/ │ ├── GlobalOverlays.vue ← snackbar、確認 dialog、toast │ └── AppTabs.vue ← 頁籤(從 App.vue 抽出) │ -├── views/ ← 維持:Page Driver(極薄) +├── views/ ← 維持:自含頁面,邏輯與 UI 同檔 │ └── maint/ -│ └── SingleRecord.vue ← ~50 行:組裝 pageModel + 掛載 PageMaintDriver +│ └── SingleRecord.vue ← ~50 行:組裝 pageModel + MaintShell 外殼 │ ├── components/ -│ ├── pages/ ← 新增:Page Component 層 -│ │ ├── PageMaintenance.vue -│ │ └── PageReport.vue -│ │ │ ├── sections/ ← 新增:Section / Shelf 層 │ │ ├── SectionSearchPanel.vue │ │ ├── SectionDataTable.vue @@ -193,10 +183,10 @@ src/ ```vue ``` -#### Layer 3: Page Component(`src/components/pages/`) +#### Layer 3: View(`src/views/`) -- **職責**:組裝完整頁面的 section 順序、處理 page-level slot override、分發頁面級事件。 -- **命名**:一律 `Page` 前綴。 -- **對齊**:App Store 的 `ProductPage.svelte`、`TodayPage.svelte`、`DefaultPage.svelte`。 +- **職責**:自含頁面的完整入口 — 組裝 page model、協調 composable、撰寫頁面 template。 +- **禁止**:頁面 UI 不再拆到另一個 page component 層。 +- **對齊**:標準 Vue SPA 慣例。 ```vue - - - + @@ -511,7 +511,7 @@ import DetailFullHeightPanel from '@/components/maint/master-detail/DetailFullHe import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue' import MntDialogCard from '@/components/maint/MntDialogCard.vue' import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue' -import PageMaint from '@/components/PageMaint.vue' +import MaintShell from '@/components/MaintShell.vue' import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow' import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm' import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters' diff --git a/src/views/maint/MasterDetailC.vue b/src/views/maint/MasterDetailC.vue index d1ed213..4abd33d 100644 --- a/src/views/maint/MasterDetailC.vue +++ b/src/views/maint/MasterDetailC.vue @@ -1,12 +1,12 @@ - + @@ -498,7 +498,7 @@ import DetailSimpleList from '@/components/maint/master-detail/DetailSimpleList. import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue' import MntDialogCard from '@/components/maint/MntDialogCard.vue' import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue' -import PageMaint from '@/components/PageMaint.vue' +import MaintShell from '@/components/MaintShell.vue' import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow' import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm' import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters' diff --git a/src/views/maint/SingleRecord.vue b/src/views/maint/SingleRecord.vue index be975ae..d3311a7 100644 --- a/src/views/maint/SingleRecord.vue +++ b/src/views/maint/SingleRecord.vue @@ -1,5 +1,5 @@ - +