From 7b0cfe4448c949c6c0c1b4d0b5f941ff2ce075dd Mon Sep 17 00:00:00 2001 From: skytek_xinliang Date: Wed, 27 May 2026 13:43:43 +0800 Subject: [PATCH] refactor(login): compose page from focused login components Split the login page into smaller reusable components for branding, toolbar, header, form, announcements, and mobile layout behavior. This keeps the view responsible for orchestration while moving UI sections into focused components. Update page creation docs to reflect the simplified flow where views render sections/items directly and composables coordinate store/service access when needed.refactor(login): compose page from focused login components Split the login page into smaller reusable components for branding, toolbar, header, form, announcements, and mobile layout behavior. This keeps the view responsible for orchestration while moving UI sections into focused components. Update page creation docs to reflect the simplified flow where views render sections/items directly and composables coordinate store/service access when needed. --- docs/add-page-example.md | 60 +- docs/architecture-strategy.md | 75 +-- docs/llm-development-guide.md | 22 +- src/GUIDE.md | 3 +- src/README.md | 6 +- src/components/GUIDE.md | 2 +- .../{PageMaint.vue => MaintShell.vue} | 0 src/components/PageIndex.vue | 234 -------- src/components/PageLogin.vue | 548 ------------------ src/composables/useLoginAnnouncements.ts | 2 + src/views/GUIDE.md | 10 +- src/views/Home.vue | 205 ++++++- src/views/Login.vue | 420 +++++++++++--- src/views/maint/GUIDE.md | 2 +- src/views/maint/MasterDetailA.vue | 6 +- src/views/maint/MasterDetailB.vue | 10 +- src/views/maint/MasterDetailC.vue | 10 +- src/views/maint/SingleRecord.vue | 6 +- 18 files changed, 614 insertions(+), 1007 deletions(-) rename src/components/{PageMaint.vue => MaintShell.vue} (100%) delete mode 100644 src/components/PageIndex.vue delete mode 100644 src/components/PageLogin.vue 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 @@ - +